You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@wicket.apache.org by Schlärmann, Bob <bo...@logica.com> on 2012/01/16 15:48:55 UTC

CompoundPropertyModel and FormComponent

Hi list,

I've created a reusable form component for editing an address, called AddressPanel. It inherits from FormComponent and consists of multiple text fields for inputting data, instances of the component get added to a Form instance.

How do I use this component together with a CompoundPropertyModel? I'm using the following code to add the component to the form:

Form<HomePage> form = new Form<HomePage>("form", new CompoundPropertyModel<HomePage>(this)); // HomePage has an instance of Person called person
form.add(new TextField<String>("person.firstname"));
form.add(new AddressPanel("person.address"));

However this gives the following exception: "Last cause: No get method defined for class: class foo.HomePage expression: street."

"street" is a text field that is added to the AddressPanel. Is it possible to have the "street" field bound to person.address.street without renaming the text field inside AddressPanel? I don't want to rename it since this way I can't reuse the component for other entities that have addresses.

Best regards,

Bob


Think green - keep it on the screen.

This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


RE: CompoundPropertyModel and FormComponent

Posted by Schlärmann, Bob <bo...@logica.com>.
Thanks for your response. After some more debugging I've found the cause and also found a solution.

The cause is that models of intermediate components, such as the Panel in my case, are never initialized if they do not already have a model. 

The parent's model is looked up in Component.initModel(), however this method uses a special method for getting the model of the parent that does not initialize the parent's model if it is not already initialized. The behaviour is intentional as there is a comment on this line:

// Get model
// Don't call the getModel() that could initialize many inbetween
// completely useless models.
// IModel model = current.getModel();
IModel<?> model = current.getModelImpl();

In my case I think this intermediate the inbetween model should get initialized. 

The workaround is to initialize the model in onBeforeRender(), before calling super.onBeforeRender(), and let the Panel implement the IFormVisitorParticipant interface. Then in IFormVisitorParticipant.processChildren() initialize the model again (by just calling getDefaultModel()). This last trick is needed in order to get the model initialized before it's children are submitted.

The complete class is as follows:

public class AddressPanel extends Panel implements IFormVisitorParticipant {
    public AddressPanel(String id) {
	super(id);
	
	add(new TextField<String>("street"));
    }
    
    protected IModel<?> initModel() {
        IModel<?> model = super.initModel();
        
        return new CompoundPropertyModel<Object>(model);
    }
    
    protected void onBeforeRender() {
	getDefaultModel(); // getDefaultModel initialized model if not yet initialized
	
       super.onBeforeRender();
    }

    public boolean processChildren() {
	getDefaultModel();
	
	return true;
    }
}

In SomePage.class you can "bind" the panel to an Address property:

Address address; // consists of a single property named street

SomePage() {
   Form<SomePage> form = new Form<SomePage>("form", new CompoundPropertyModel(this));
   form.add(new AddressPanel("address"));
   add(form);
}


This solution seems a bit awkward though so I'm using a constructor with model solution in my application.

Best regards,

Bob


> At this point I would override/debug method updateModel() inside
> AddressPanel to see if model's object is modified by this method .
> Just my 2 cents...
> >> Yes, I think you are doing it "the Wicket way", but your snippet and
> >> mine should work. Do you modify components' model somewhere else?
> > No, I don't think so. The page to which the component is added is
> constructed as follows:
> >
> > CompoundPropertyModel<HomePage>  model = new
> CompoundPropertyModel<HomePage>(this);
> > Form<HomePage>  form = new Form<HomePage>("form", model);
> > form.add(new TextField<String>("person.firstname"));
> > form.add(new AdresPanel("person.adres"));
> >
> > No other code modifies the model.
> >
> >>> Which model do you get if you call getDefaultModel() inside oninitialize?
> > The result of getDefaultModel() is an instance of
> CompoundPropertyModel$AttachedCompoundPropertyModel, with owner set to the
> AdresPanel and with target set to a CompoundPropertyModel which in turn has
> target HomePage.
> >
> > I noticed that upon initializing the model is set correctly. However when
> inspecting the model in onBeforeRender() during the submit request the target
> of the model of the AddressPanel.street model is set to HomePage.
> >
> >>> Thanks for your reply. I've tried it but it still gave the same error.
> >>>
> >>> However I also tried the following modified version of your idea:
> >>>
> >>> In AddressPanel.java:
> >>>
> >>> @Override
> >>> protected void onInitialize() {
> >>> 	super.onInitialize();
> >>>          Object o = getDefaultModelObject();
> >>>
> >>>          setDefaultModel(new
> CompoundPropertyModel(getDefaultModelObject()));
> >>> }
> >>>
> >>> With the above code I can now load the page, also the
> >> getDefaultModelObject() returns the correct Address instance. Unfortunately
> >> upon submitting the form I get the same exception again ("No get method
> >> defined for class: class foo.HomePage expression: street").
> >>> By the way: am I doing things "the Wicket way"? Is this how you would
> reuse
> >> parts of a form in Wicket?
> >>>
> >>>
> >>> Best regards,
> >>>
> >>> Bob
> >>>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> >> For additional commands, e-mail: users-help@wicket.apache.org
> >>
> >
> > Think green - keep it on the screen.
> >
> > This e-mail and any attachment is for authorised use by the intended
> recipient(s) only. It may contain proprietary material, confidential
> information and/or be subject to legal privilege. It should not be copied,
> disclosed to, retained or used by, any other party. If you are not an intended
> recipient then please promptly delete this e-mail and any attachment and all
> copies and inform the sender. Thank you.
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
> 


Think green - keep it on the screen.

This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: CompoundPropertyModel and FormComponent

Posted by Andrea Del Bene <ad...@ciseonweb.it>.
At this point I would override/debug method updateModel() inside 
AddressPanel to see if model's object is modified by this method .
Just my 2 cents...
>> Yes, I think you are doing it "the Wicket way", but your snippet and
>> mine should work. Do you modify components' model somewhere else?
> No, I don't think so. The page to which the component is added is constructed as follows:
>
> CompoundPropertyModel<HomePage>  model = new CompoundPropertyModel<HomePage>(this);
> Form<HomePage>  form = new Form<HomePage>("form", model);
> form.add(new TextField<String>("person.firstname"));
> form.add(new AdresPanel("person.adres"));
>
> No other code modifies the model.
>
>>> Which model do you get if you call getDefaultModel() inside oninitialize?
> The result of getDefaultModel() is an instance of CompoundPropertyModel$AttachedCompoundPropertyModel, with owner set to the AdresPanel and with target set to a CompoundPropertyModel which in turn has target HomePage.
>
> I noticed that upon initializing the model is set correctly. However when inspecting the model in onBeforeRender() during the submit request the target of the model of the AddressPanel.street model is set to HomePage.
>
>>> Thanks for your reply. I've tried it but it still gave the same error.
>>>
>>> However I also tried the following modified version of your idea:
>>>
>>> In AddressPanel.java:
>>>
>>> @Override
>>> protected void onInitialize() {
>>> 	super.onInitialize();
>>>          Object o = getDefaultModelObject();
>>>
>>>          setDefaultModel(new CompoundPropertyModel(getDefaultModelObject()));
>>> }
>>>
>>> With the above code I can now load the page, also the
>> getDefaultModelObject() returns the correct Address instance. Unfortunately
>> upon submitting the form I get the same exception again ("No get method
>> defined for class: class foo.HomePage expression: street").
>>> By the way: am I doing things "the Wicket way"? Is this how you would reuse
>> parts of a form in Wicket?
>>>
>>>
>>> Best regards,
>>>
>>> Bob
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
>> For additional commands, e-mail: users-help@wicket.apache.org
>>
>
> Think green - keep it on the screen.
>
> This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


RE: CompoundPropertyModel and FormComponent

Posted by Schlärmann, Bob <bo...@logica.com>.
> Yes, I think you are doing it "the Wicket way", but your snippet and
> mine should work. Do you modify components' model somewhere else? 
No, I don't think so. The page to which the component is added is constructed as follows:

CompoundPropertyModel<HomePage> model = new CompoundPropertyModel<HomePage>(this);
Form<HomePage> form = new Form<HomePage>("form", model);
form.add(new TextField<String>("person.firstname"));
form.add(new AdresPanel("person.adres"));

No other code modifies the model.

> > Which model do you get if you call getDefaultModel() inside oninitialize?
The result of getDefaultModel() is an instance of CompoundPropertyModel$AttachedCompoundPropertyModel, with owner set to the AdresPanel and with target set to a CompoundPropertyModel which in turn has target HomePage.

I noticed that upon initializing the model is set correctly. However when inspecting the model in onBeforeRender() during the submit request the target of the model of the AddressPanel.street model is set to HomePage.

> > Thanks for your reply. I've tried it but it still gave the same error.
> >
> > However I also tried the following modified version of your idea:
> >
> > In AddressPanel.java:
> >
> > @Override
> > protected void onInitialize() {
> > 	super.onInitialize();
> >         Object o = getDefaultModelObject();
> >
> >         setDefaultModel(new CompoundPropertyModel(getDefaultModelObject()));
> > }
> >
> > With the above code I can now load the page, also the
> getDefaultModelObject() returns the correct Address instance. Unfortunately
> upon submitting the form I get the same exception again ("No get method
> defined for class: class foo.HomePage expression: street").
> >
> > By the way: am I doing things "the Wicket way"? Is this how you would reuse
> parts of a form in Wicket?
> >
> >
> >
> > Best regards,
> >
> > Bob
> >
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
> 


Think green - keep it on the screen.

This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: CompoundPropertyModel and FormComponent

Posted by Andrea Del Bene <ad...@ciseonweb.it>.
Yes, I think you are doing it "the Wicket way", but your snippet and 
mine should work. Do you modify components' model somewhere else? Which 
model do you get if you call getDefaultModel() inside oninitialize?
> Thanks for your reply. I've tried it but it still gave the same error.
>
> However I also tried the following modified version of your idea:
>
> In AddressPanel.java:
>
> @Override
> protected void onInitialize() {
> 	super.onInitialize();
>         Object o = getDefaultModelObject();
>
>         setDefaultModel(new CompoundPropertyModel(getDefaultModelObject()));
> }
>
> With the above code I can now load the page, also the getDefaultModelObject() returns the correct Address instance. Unfortunately upon submitting the form I get the same exception again ("No get method defined for class: class foo.HomePage expression: street").
>
> By the way: am I doing things "the Wicket way"? Is this how you would reuse parts of a form in Wicket?
>
>
>
> Best regards,
>
> Bob
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


RE: CompoundPropertyModel and FormComponent

Posted by Schlärmann, Bob <bo...@logica.com>.
Thanks for your reply. I've tried it but it still gave the same error. 

However I also tried the following modified version of your idea:

In AddressPanel.java:

@Override
protected void onInitialize() {
	super.onInitialize();
       Object o = getDefaultModelObject();
        
       setDefaultModel(new CompoundPropertyModel(getDefaultModelObject()));
}

With the above code I can now load the page, also the getDefaultModelObject() returns the correct Address instance. Unfortunately upon submitting the form I get the same exception again ("No get method defined for class: class foo.HomePage expression: street").

By the way: am I doing things "the Wicket way"? Is this how you would reuse parts of a form in Wicket? 



Best regards,

Bob
> Hi,
> 
> I think you need to build a CompoundPropertyModel inside the component
> itself. Override onInitialize method of AddressPanel and try with
> something like this:
> 
> @Override
>      protected void onInitialize() {
>          super.onInitialize();
>          setDefaultModel(new CompoundPropertyModel(getDefaultModel()));
>      }
> 
> 
> > Hi list,
> >
> > I've created a reusable form component for editing an address, called
> AddressPanel. It inherits from FormComponent and consists of multiple text
> fields for inputting data, instances of the component get added to a Form
> instance.
> >
> > How do I use this component together with a CompoundPropertyModel? I'm using
> the following code to add the component to the form:
> >
> > Form<HomePage>  form = new Form<HomePage>("form", new
> CompoundPropertyModel<HomePage>(this)); // HomePage has an instance of Person
> called person
> > form.add(new TextField<String>("person.firstname"));
> > form.add(new AddressPanel("person.address"));
> >
> > However this gives the following exception: "Last cause: No get method
> defined for class: class foo.HomePage expression: street."
> >
> > "street" is a text field that is added to the AddressPanel. Is it possible
> to have the "street" field bound to person.address.street without renaming the
> text field inside AddressPanel? I don't want to rename it since this way I
> can't reuse the component for other entities that have addresses.
> >
> > Best regards,
> >
> > Bob
> >
> >
> > Think green - keep it on the screen.
> >
> > This e-mail and any attachment is for authorised use by the intended
> recipient(s) only. It may contain proprietary material, confidential
> information and/or be subject to legal privilege. It should not be copied,
> disclosed to, retained or used by, any other party. If you are not an intended
> recipient then please promptly delete this e-mail and any attachment and all
> copies and inform the sender. Thank you.
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> > For additional commands, e-mail: users-help@wicket.apache.org
> >
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
> 


Think green - keep it on the screen.

This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org


Re: CompoundPropertyModel and FormComponent

Posted by Andrea Del Bene <ad...@ciseonweb.it>.
Hi,

I think you need to build a CompoundPropertyModel inside the component 
itself. Override onInitialize method of AddressPanel and try with 
something like this:

@Override
     protected void onInitialize() {
         super.onInitialize();
         setDefaultModel(new CompoundPropertyModel(getDefaultModel()));
     }


> Hi list,
>
> I've created a reusable form component for editing an address, called AddressPanel. It inherits from FormComponent and consists of multiple text fields for inputting data, instances of the component get added to a Form instance.
>
> How do I use this component together with a CompoundPropertyModel? I'm using the following code to add the component to the form:
>
> Form<HomePage>  form = new Form<HomePage>("form", new CompoundPropertyModel<HomePage>(this)); // HomePage has an instance of Person called person
> form.add(new TextField<String>("person.firstname"));
> form.add(new AddressPanel("person.address"));
>
> However this gives the following exception: "Last cause: No get method defined for class: class foo.HomePage expression: street."
>
> "street" is a text field that is added to the AddressPanel. Is it possible to have the "street" field bound to person.address.street without renaming the text field inside AddressPanel? I don't want to rename it since this way I can't reuse the component for other entities that have addresses.
>
> Best regards,
>
> Bob
>
>
> Think green - keep it on the screen.
>
> This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
> For additional commands, e-mail: users-help@wicket.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@wicket.apache.org
For additional commands, e-mail: users-help@wicket.apache.org