001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.markup.html.basic; 018 019import org.apache.wicket.Component; 020import org.apache.wicket.markup.html.WebMarkupContainer; 021import org.apache.wicket.util.lang.Args; 022 023 024/** 025 * <code><wicket:enclosure></code> is nice and prevents that users have to add boilerplate to 026 * their application. But it is not without problems. The child components are children in the 027 * markup, but the auto-component generated for the enclosure tag will not magically re-parent the 028 * child components. Thus, the markup hierarchy and the component hierarchy will be out of sync. The 029 * automatically created enclosure container will be created alongside its "children" with both 030 * attached to the very same parent container. That leads to a tricky situation since e.g. 031 * <code>onBeforeRender()</code> will be called for enclosure children even if the enclosure is made 032 * invisible by it controlling child. 033 * <p> 034 * On top auto-components cannot keep any state. A new instance is created during each render 035 * process and automatically deleted at the end. That implies that we cannot prevent 036 * <code>validation()</code> from being called, since validation() is called before the actual 037 * render process has started. 038 * </p> 039 * <p> 040 * Where any of these problems apply, you may replace the tag and manually add this simple container 041 * which basically does the same. But instead of adding the children to the Page, Panel whatever, 042 * you must add the children to this container in order to keep the component hierarchy in sync. 043 * </p> 044 * 045 * <p> 046 * <strong>Note</strong>: Make sure the markup element associated with this {@link EnclosureContainer} 047 * is anything but <em><wicket:enclosure></em>, e.g. a <div>, a <span> or even a 048 * <wicket:container> 049 * </p> 050 * 051 * @author Juergen Donnerstag 052 * @since 1.5 053 */ 054public class EnclosureContainer extends WebMarkupContainer 055{ 056 private static final long serialVersionUID = 1L; 057 058 /** The child component to delegate the isVisible() call to */ 059 private final Component child; 060 061 /** 062 * Construct. 063 * 064 * @param id 065 * @param child 066 * child component that will control the visibility of the enclosure 067 */ 068 public EnclosureContainer(final String id, final Component child) 069 { 070 super(id); 071 072 Args.notNull(child, "child"); 073 074 this.child = child; 075 076 // Usually we don't want this extra tag 077 setRenderBodyOnly(true); 078 } 079 080 /** 081 * Overridden to set the visibility depending on children {@link #determineVisibility()}. 082 */ 083 @Override 084 protected void onConfigure() 085 { 086 super.onConfigure(); 087 child.configure(); 088 089 setVisible(child.determineVisibility()); 090 } 091}