There is.

As you noticed you can change any property you like /before/ the render phase.

Another way to put metadata on components is annotations. This is for example used for security type of things. You can intercept the creation and rendering of each component in Wicket (in your application's init call getSecuritySettings().setAuthorizationStrategy(...)). The strategy object you pass here can analyze the annotation on the component and (dis)allow creation, rendering and enabled state (what enabled means is up to the component). Wicket-auth-roles and wicket-auth-roles-example are a good showcase.

Regards,
   Erik.


tetsuo wrote:
Hi,

What I'm trying to do is to change components properties (visible/hidden,
editable/read-only, etc.) depending on some external context (authorization,
model state, etc.), but I don't want to have to change their properties on
events. Instead, I'd like to modularize these kinds of modifications and add
it to components.

I tried to do this with IBehavior implementations, but it didn't work
straight forward, because you can't modify some properties while rendering
the component (wicket throws an exception).

What I did for this to work was to add an IBehavior to the Page, which
iterates over the component tree, modifying what is needed. To be able to
add modifications to components themselves, I created another interface
(IComponentModifier), which must be added as an IBehavior (implementations
must implement both interfaces). This is because that was the only way I've
found to add some sort of metadata to components. The IBehavior
implementation would be 'NoOp' in most cases. The code is as follows:


public interface IComponentModifier {
    void modify(Component component);
}
public abstract class AbstractComponentModifier extends AbstractBehavior
implements IComponentModifier {
    public abstract void modify(Component component);
}
public class ChildrenModifier extends AbstractBehavior {
    final String[] roles;
    public ChildrenModifier(String... roles) {
        this.roles = Arrays.copyOf(roles, roles.length);
    }
    @Override
    public void beforeRender(Component component) {
        super.beforeRender(component);
        processChild(component);
    }
    private void processChild(Component component) {
        for (IBehavior b : component.getBehaviors())
            if (b instanceof IComponentModifier)
                ((IComponentModifier) b).modify(component);
        if (component instanceof MarkupContainer)
            for (Component child : IteratorIterable.get(((MarkupContainer)
component).iterator()))
                processChild(child);
    }
}

public class HomePage extends WebPage {
    String text = "blablabla";
    private final Component label;
    public HomePage(final PageParameters parameters) {
        *add(new ChildrenModifier());*

        label = new Label("hidden", new PropertyModel<String>(this,
"text")).add(*new RoleBasedModifier("ADMIN")*);
        add(new Label("message", "If you see this message wicket is properly
configured and running!"));
        Form<HomePage> form = new Form<HomePage>("form", new
CompoundPropertyModel<HomePage>(this));
        form.add(new TextField<String>("text"));
        form.add(label);
        add(form);
    }
    class RoleBasedModifier extends AbstractComponentModifier {
        protected final Set<String> roles;
        public RoleBasedModifier(String... roles) {
            this.roles = new HashSet<String>(Arrays.asList(roles));
        }
        @Override
        public void modify(Component component) {
            for (String role : roles)
                if (((WebRequest)
getRequest()).getHttpServletRequest().isUserInRole(role))
                    component.setVisibilityAllowed(true);
            component.setVisibilityAllowed(false);
        }
    }
}

Is there another (better) approach?

Tetsuo



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to