tags:

views:

30

answers:

2

In wicket AttributeModifier doesn't change attribute "class" for AjaxLink. It should change class attribute and change how link looks like.

public class TestPage extends WebPage {
    private AjaxLink link1;
    private AjaxLink link2;

    public TestPage() {
        super();

        link1 = new AjaxLink("link1") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(AjaxRequestTarget target) {
                switchView("view1");
            }
        };

        link2 = new AjaxLink("link2") {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(AjaxRequestTarget target) {
                switchView("view2");
            }
        };

        link1.setOutputMarkupId(true);
        link2.setOutputMarkupId(true);

        link1.add(new AttributeModifier("class", true, new Model<String>("active")));
        link2.add(new AttributeModifier("class", true, new Model<String>("inactive")));

        add(link1);
        add(link2);
    }

    private void switchView(String viewName) {
        if (viewName.equals("view1")) {
            link1.add(new AttributeModifier("class", true, new Model<String>("active")));
            link2.add(new AttributeModifier("class", true, new Model<String>("inactive")));
        } else if (viewName.equals("view2")) {
            link1.add(new AttributeModifier("class", true, new Model<String>("inactive")));
            link2.add(new AttributeModifier("class", true, new Model<String>("active")));
        }
    }
}

Corresponding html file looks like:

<html xmlns:wicket>
<body>
<wicket:extend>
 <div id="tabs">
 <ul>
  <li><a wicket:id="link1">View1</a></li>
  <li><a wicket:id="link2">View2</a></li>
 </ul>
 </div>
</wicket:extend>
</body>
</html>

Thanks

+1  A: 

You're not actually telling wicket to do anything in the ajax response.

A likely fix is to add the lines:

target.addComponent(link1);
target.addComponent(link2);

(or a call to a function doing this) to both of your onClick methods.

Don Roby
D'oh! I didn't work with wicket for a while and forgot about addComponent() method. It works. Thanks
zdmytriv
+1  A: 

The correct answer was already given, you have to add the components to the AjaxTarget. However, for the sake of creating more "Wickety" code, you could rewrite your class to something like this:

public class TestPage extends WebPage {
    private AjaxLink link1;
    private AjaxLink link2;

    public TestPage() {
        super();

        final Model<Boolean> link1Model = new Model<Boolean>(Boolean.True);
        final Model<Boolean> link2Model = new Model<Boolean>(Boolean.False);

        link1 = new AjaxLink<Boolean>("link1", link1Model) {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(AjaxRequestTarget target) {
                this.getModel().setObject(!this.getModel().getObject());
                target.addComponent(this);
            }
        };

        link2 = new AjaxLink<Boolean>("link2", link2Model) {
            private static final long serialVersionUID = 1L;

            @Override
            public void onClick(AjaxRequestTarget target) {
                this.getModel().setObject(!this.getModel().getObject());
                target.addComponent(this);
            }
        };

        link1.setOutputMarkupId(true);
        link2.setOutputMarkupId(true);

        link1.add(new AttributeModifier("class", true, new Model<String>() {
           public String getObject() {
              return link1Model.getObject() ? "active" : "inactive";
           }
        }));
        link2.add(new AttributeModifier("class", true, new Model<String>() {
           public String getObject() {
              return link1Model.getObject() ? "active" : "inactive";
           }
        }));

        add(link1);
        add(link2);
    }
}

It makes use of models and that is recommended in Wicket. However, there is heavy code duplication going on there, so I would maybe suggest going for a distinct component:

public final class ActiveInactiveLink extends AjaxFallbackLink<Boolean> {
    public ActiveInactiveLink(String id) {
        super(id, new Model<Boolean>(Boolean.True));
        this.add(new AttributeModifier("class", true, new Model<String>() {
            public String getObject() {
               Model<Boolean> model = ActiveInactiveLink.this.getModel();
               return model.getObject() ? "active" : "inactive";
            }
         }));
         this.setOutputMarkupId(true);
    }

    @Override
    public void onClick(AjaxRequestTarget target) {
       this.getModel().setObject(!this.getModel().getObject());
       target.addComponent(this);
    }

    @Override
    public void setModel(IModel<Boolean> model) {
        if(model == null)
           return;
        this.model = model;
    }

 }

 public class TestPage extends WebPage {
        private AjaxLink link1;
        private AjaxLink link2;

        public TestPage() {
            link1 = new ActiveInactiveLink("link1");
            link2 = new AjaxLink<Boolean>("link2");

            add(link1);
            add(link2);
        }
    }

All this stuff is not tested or compiled, of course, so no guarantees. :)

Also, the guys from the Wicket mailing list will most definitely come up with something more elegant...

Enjoy.

LeChe