tags:

views:

52

answers:

3

HI guys, I wanted to add an AJAX Event to my Homepage, but it doesn't work! I figured out, that if I delete the onComponentTag function it works well. I have no clue why this happend, maybe you can help me! Thats my Code:

  final TextField<String> searchInput = new TextField<String>("searchInput", model) {

    @Override
    protected void onComponentTag(final ComponentTag tag) {
     super.onComponentTag(tag);
     tag.put("id", this.getId());
     if (params.getString("search") != null) {
      tag.put("value", params.getString("search"));
     }
    }
   };

   searchInput.add(new AjaxFormComponentUpdatingBehavior("onfocus") {
    @Override
    protected void onUpdate(final AjaxRequestTarget target) {
     System.out.print("never saw that message :(");
     searchInput.setDefaultModelObject("");
     target.addComponent(searchInput);
    }

   });

Thx a lot for helping me! CU

+2  A: 
tag.put("id", this.getId());

is not the way to do it in wicket.

instead, use

component.setOutputMarkupId(true)

(either in your component constructor or in your behavior's bind() method) to make wicket write the id, and if you absolutely need to control what the id is (which is almost never the case) you can do

component.setMarkupId("myId")

also, you probably shouldn't assign the tag value yourself, use a model (model handling is extremely smart in wicket, read more about models). There are valid uses for onComponentTag, but they are way beyond what you are doing. Let wicket do what wicket does best and everything will be fine.


EDIT: OK, some more clarification

have a look at the source code of AjaxFormComponentUpdatingBehavior, especially the part where the javascript event handler is generated.

protected final CharSequence getEventHandler()
{
    return generateCallbackScript(
                    new AppendingStringBuffer("wicketAjaxPost('")
                    .append(getCallbackUrl(false)).append(
        "', wicketSerialize(Wicket.$('" 
                         + getComponent().getMarkupId() + "'))"));
}

as you can see, wicket uses getMarkupId() to determine the actual id. The id you set using tag.put(id) is totally unknown to wicket and hence the behavior cannot work.

The standard thing to do is setOutputMarkupId(true). This is the only proper way to tell wicket to render the id (other than setOutputMarkupPlaceholder(true), which internally calls the former method). That way you make sure that the id wicket writes is the id wicket knows about. If this doesn't render the id, you are probably breaking some default behavior by overwriting onComponentTag.

Have a look at the source code of Component, especially at onComponentTag(), the method you are overriding:

protected void onComponentTag(final ComponentTag tag) {
    // if(setOutputMarkupId(true) was set)
    if (getFlag(FLAG_OUTPUT_MARKUP_ID)) {

        // set id attribute
        tag.put(MARKUP_ID_ATTR_NAME, getMarkupId());
    }
}

[The comments are mine. BTW, this is the source of an ancient version, but I didn't find any current source online, and the functionality hasn't changed.]

Now if, as in your case, you want to set the component id manually, you must use

component.setMarkupId("myId")

and of course

setOutputMarkupId(true)

as well. If that doesn't work, go to the wicket JIRA site and file a bug. But I doubt it, this is standard functionality that works for thousands of users.

seanizer
sorry but I can't follow you. 1) I tryed setOutputMarkupId(true) but it doesn't print out my id! I need an ID for my CSS!2) I never wanted to change the ID and never will :)3) this doesn't solve my probelm :(Maybe I'm just not clever enough :) Please help!
Sylvus
see my updated answer. you need to use both setMarkupId(myId) and setOutputMarkupId(true)
seanizer
+1  A: 

Firstly, you don't need to be overriding onComponentTag() at all. As seanizer states, if your really need to specify a markup ID yourself, use setMarkupId(id). You should understand why it is recommended that Wicket manages component IDs.

Secondly, the value attribute that you are adding is unnecessary - Wicket adds this automatically for this component. The value assigned is the value of the component's model object. See the source for TextField.onComponentTag().

Thirdly, again as seanizer states, components that are to be updated by ajax need to output their markup IDs - Wicket's ajax implementation uses the ID as the selector for the element. Additionally, all Wicket ajax behaviours that extend AbstractDefaultAjaxBehavior automatically set outputMarkupId(true) on the component they are bound to (see the source for AbstractDefaultAjaxBehavior.onBind()). This includes AjaxFormComponentUpdatingBehavior.

So:

String id = "searchInput";
final TextField<String> searchInput = new TextField<String>(id, model);
searchInput.setMarkupId(id);

searchInput.add(new AjaxFormComponentUpdatingBehavior("onfocus") {
  @Override
  protected void onUpdate(final AjaxRequestTarget target) {
    System.out.print("never saw that message :(");
    searchInput.setDefaultModelObject("");
    target.addComponent(searchInput);
  }
});

Finally, I'd question what you're actually trying to achieve with this behaviour. I don't see any reason to round-trip this event to the server. Surely some client-side JS is more appropriate?

ireddick
@ireddick you forgot setOutputMarkupId(true) :-)
seanizer
See the source for AbstractDefaultAjaxBehavior.onBind() - the behaviour sets the flag for you (sorry this wasn't clear - I've edited my answer to make it clearer).
ireddick
A: 

Ok Thx guys, got it now! :) Yeah I'm a little slow, but thanks a lot! CU!

Sylvus
This isn't an answer - don't do this.
ireddick