How to remove a CSS class from a Wicket component?

Jonik picture Jonik · Apr 13, 2012 · Viewed 10.6k times · Source

It's pretty straightforward to dynamically add a CSS class to a component in Java code using an AttributeAppender:

component.add(new AttributeAppender("class", true, new Model<String>("foo"), " "));

Or, if you've extracted the above into an appropriate utility method or class, simply something like:

component.add(WicketUtils.cssClassAppender("foo"));

But how can I remove a CSS class?

You can easily remove all CSS classes by clearing the class attribute altogether:

component.add(new SimpleAttributeModifier("class", ""));

...but that is not acceptable if the component has other CSS classes that you do not wish to remove.

Wicket 1.4 (but feel free to post advice specific to later versions too).

Answer

Jonik picture Jonik · Apr 13, 2012

Here's one way I came up with:

public class CssClassRemover extends AttributeModifier {
    public CssClassRemover(String cssClass) {
        super("class", false, new Model<String>(cssClass));
    }

    @Override
    protected String newValue(String currentValue, String valueToRemove) {
        // NB: naive approach; breaks with e.g. "foo foo-bar" & "foo"
        return currentValue.replaceAll(valueToRemove, "");
    }
}

The code that uses the above helper would then be:

component.add(new CssClassRemover("foo"))

(Of course you can also just create anonymous AttributeModifier subclasses as needed, but putting the logic in a separate utility class or method cleans it up a lot.)

Edit: An improved version of newValue() that handles corner cases better (see comment by biziclop). NB: uses Guava. (You're welcome to post simpler (regex?) versions.)

@Override
protected String newValue(String currentValue, String valueToRemove) {
    if (currentValue == null) return "";

    Set<String> classes = Sets.newHashSet(Splitter.on(" ").split(currentValue));
    classes.remove(valueToRemove);
    return Joiner.on(" ").join(classes); 
}