tags:

views:

35

answers:

2

I am implementing the Wicket IBehavior interface and want my behavior change the body of a component (or somehow update the model) from the onComponentTag method. Is there a way to do this?

@Override
public void onComponentTag(final Component component, final ComponentTag tag)
{
    String myValue = tag.getAttribute("myAttribute");

    // TODO: Based on the value of this attribute, update the body/model of the component


    super.onComponentTag(component, tag);
}

Edit: I would like to grab an attribute from the html which specifies the maximum number of allowed characters for the element and then programmatically truncate the body of the element if needed.

Example:

<span wicket:id="myLabel" maxChars="10">The body of my tag</span>

would be replaced with:

<span wicket:id="myLabel" maxChars="10">The bod...</span>
A: 

You might be able to do this by getting the model from the component, getting the object from the model and making whatever changes you need on the object, but onComponentTag is not the best place for work that changes the model.

This method is called during the rendering process, at a point when your page may have been partially rendered. Any part of the page that has already been rendered will have been rendered with the prior state of the model. As models can be shared among components, your resulting page might be inconsistent.

If you're trying to change the rendered body, that is another story, and perfectly reasonable work to do in this method. It generally involves calling methods on the ComponentTag tag parameter.

What is the problem you're trying to solve by creating this behavior? Perhaps we can think of a better way.

EDIT:

For the particular case of trimming the display on a label, you're likely better served by simply subclassing the Label component approximately as follows:

public class TrimmedLabel extends Label {
    private int size;

    public TrimmedLabel(String id, int size) {
        super(id);
        this.size = size;
    }

    public TrimmedLabel(String id, String label, int size) {
        super(id, label);
        this.size = size;
    }

    public TrimmedLabel(String id, IModel model, int size) {
        super(id, model);
        this.size = size;
    }

    @Override
    protected void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
        String value = getModelObjectAsString();
        if (value.length() > size) {
            value = value.substring(0, size);
        }
        replaceComponentTagBody(markupStream, openTag, value);
    }
}
Don Roby
I want to specify the maximum number of characters allowable for the body of the label in the html and then grab that value and potentially truncate the text.
Clayton
I was hoping to encapsulate this functionality in a behavior that could be applied to a variety of components, but based on my research I don't think it is possible.
Clayton
+1  A: 

Derived from the Quickstart http://wicket.apache.org/start/quickstart.html my suggestion would look like this:

    add(new Label("message", "If you see this message wicket is properly configured and running") {

        @Override
        protected void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
            String myAttrib = openTag.getAttribute("myAttrib");
            replaceComponentTagBody(markupStream, openTag, getDefaultModelObjectAsString().substring(0, Integer.valueOf(myAttrib)));
        }

    });

Don't forget to watch for NumberFormat Exceptions though.

Also donroby's suggestions do all aply. Don't mess with the model if not needed.

mfunk
+1: This may be more current than mine, as I was working from a Wicket 1.3 install.
Don Roby