Is okay for your form to receive an IModel and is also okay not to receive
any models and use a LodableDetachableModel warpped in a
CompoundPropertyModel internally as per my precious e-mail.
Okay, let's stick with the form constructor having an IModel argument.
What's this model? DetachableCnavUrlModel?
Why not just a simple LoadableDetachableModel<T>?
LoadableDetachableModel<CnavUrl> cnavUrlLDM = new
LoadableDetachableModel<CnavUrl>() {
private static final long serialVersionUID = 1L;
@Override
protected CnavUrl load() {
return myDao.getCnavUrl(some id here);
}
};
Now wrap that in a CompoundPropertyModel like so:
Form form = new CnavForm("cnavForm", new
CompoundPropertyModel<CnavUrl>(cnavUrlLDM));
Your CnavForm would then use the property names of CnavUrl for its component
IDs.
Hope that makes more sense for you now, but you should really re-read
chapter 9 "Wicket models and forms" of the Wicket Free Guide at (it will
save you lots of time!):
http://wicket.apache.org/learn/books/freeguide.html
~ Thank you,
Paul Bors
-----Original Message-----
From: Daniel Watrous [mailto:[email protected]]
Sent: Tuesday, July 23, 2013 4:39 PM
To: [email protected]
Subject: Re: Form questions
I've had a difficult time following your recommendations. However I think
I'm getting closer.
Part of the disconnect is that right now, as I show above, the model object
I create is in the Form, not the Page. In my Page I create an instance of my
Form like this:
Form form = new CnavForm("cnavForm");
add(form);
So, the first step I've taken is to implement a constructor for my Form that
receives an IModel and, rather than create my CnavUrl, I get it from the
IModel:
CnavUrl cnavUrl = (CnavUrl) model.getObject();
setModel(new Model((Serializable) cnavUrl));
Now I create my Form object like this:
DetachableCnavUrlModel cnavUrlModel = new DetachableCnavUrlModel(new
MorphiaCnavUrl());
Form form = new CnavForm("cnavForm", cnavUrlModel);
add(form);
I'm now at the page level when I create my Model and I have a
DetachableCnavUrlModel, which I also use when displaying them.
if (cnavid != null) {
cnavUrlModel = new
DetachableCnavUrlModel(cnavUrlDAO.getCnavById(cnavid));
} else {
cnavUrlModel = new DetachableCnavUrlModel(new MorphiaCnavUrl());
}
Form form = new CnavForm("cnavForm", cnavUrlModel);
add(form);
This way on edit I have a prepopulated form.
To answer my other question about the link, I created a PageParameters
object and used setResponsePage like this
item.add(new Link("editlink") {
@Override
public void onClick() {
PageParameters editParameters = new
PageParameters();
editParameters.add("cnavid",
((MorphiaCnavUrl)cnavUrl).getId());
setResponsePage(CnavModify.class, editParameters);
}
});
I can then use the value in the parameters to set cnavid
if (parameters.get("cnavid").toString() != null) {
cnavid = new ObjectId(parameters.get("cnavid").toString());
}
Thanks for all the help.
Daniel
On Fri, Jul 19, 2013 at 9:38 AM, Paul Bors <[email protected]> wrote:
> For stateless pages it would create a new one each time (add the
> DebugBar to your pages and see if your page is stateless or not and
> also see what the model is per component).
>
> For when Wicket serializes your page, you don't want a PropertyModel
> alone, you want a detachable model (see section 9.6 of the Wicket Free
> Guide or go over chapter 9 again "Wicket models and forms"). You need
> to wrap a Detachable model inside a Property model like so:
>
> add(new TextField("url", new PropertyModel<MorphiaCnavUrl>(new
> LoadableDetachableModel<MorphiaCnavUrl>(cnavUrl), "URL"))
> .setRequired(true)
> .add(new UrlValidator()));
>
> Is best to use a CompoundPropertyModel for the entire form and get to
> your POJO that feeds the entire form (or panel) via a detachable model.
>
> The LoadableDetachableModel is desined to only serialize the record ID
> for which you can later retrieve the entire object from your persistence
layer.
>
> ~ Thank you,
> Paul Bors
>
> -----Original Message-----
> From: Daniel Watrous [mailto:[email protected]]
> Sent: Friday, July 19, 2013 11:24 AM
> To: [email protected]
> Subject: Re: Form questions
>
> Paul,
>
> Thanks. I get that and understand how the Model happens. As you can
> see, the instance of the model object is created in the constructor.
> So the first question I had is whether a new instance is created for
> every request or if there's one instance that's serialized. I suspect
> it's the second, knowing how Wicket treats sessions. In that case, I
> need some way on a per request basis to load the model from the
> database.
>
> The other question I had is how to create a link that sends the ID to
> the page that renders the form. I need to create a link to that page,
> include an ID value with the request and then access that ID within
> the form for my query to load that object from the DB.
>
> Daniel
>
>
> On Thu, Jul 18, 2013 at 5:14 PM, Paul Bors <[email protected]> wrote:
>
> > Okay let's pre-populate this field:
> >
> > add(new TextField("url", new PropertyModel(cnavUrl, "URL"))
> > .setRequired(true)
> > .add(new UrlValidator()));
> >
> > Its mode is a new PropertyModel(cnavUrl, "URL"), which is the
> > "CnavUrl cnavUrl = new MorphiaCnavUrl();".
> > So it's the cnavUrl.getUrl() value.
> >
> > What do you get when you call new MorphiaCnavUrl().getUrl()?
> > That's what should appear in the TextField when you first load the
> > page (normally read form the DB).
> >
> > ~ Thank you,
> > Paul Bors
> >
> > -----Original Message-----
> > From: Daniel Watrous [mailto:[email protected]]
> > Sent: Thursday, July 18, 2013 6:03 PM
> > To: [email protected]
> > Subject: Re: Form questions
> >
> > I've made a lot of progress and been through chapters 9 and 10 of
> > Wicket Free Guide, but I'm still stumped on point #2, pre-populating
> > the
> form.
> > Here's what I have right now:
> >
> > public class CnavForm extends Form {
> >
> > @Inject private CnavUrlDAO cnavUrlDAO;
> >
> > public CnavForm(String id) {
> > super(id);
> > CnavUrl cnavUrl = new MorphiaCnavUrl();
> > setModel(new Model((Serializable) cnavUrl));
> >
> > add(new TextField("url", new PropertyModel(cnavUrl, "URL"))
> > .setRequired(true)
> > .add(new UrlValidator()));
> > add(new HiddenField("objectid", new PropertyModel(cnavUrl,
> > "id")));
> >
> > add(new Button("publish") {
> > @Override
> > public void onSubmit() {
> > CnavUrl cnavUrl = (CnavUrl)
> CnavForm.this.getModelObject();
> > // check for existing record to know if this is a
> > create or update
> > if (((MorphiaCnavUrlModel)cnavUrl).getId() == null) {
> > // create
> > cnavUrlDAO.save(cnavUrl);
> > } else {
> > // update
> > cnavUrlDAO.save(cnavUrl);
> > }
> > }
> > });
> > }
> > }
> >
> > I need to know how to do two things.
> > 1) how to link to the page that displays the form, and pass it the
> > ID for the record I want to edit
> > 2) load the object from the database and have it replace the model I
> > create in the constructor
> >
> > Obviously I can make a database call and get the object. Is the
> > constructor called every time the page is requested, so that I could
> > check for an ID and either create the model or load it from the
> > database? If so, then I just need help with #1.
> >
> > Thanks,
> > Daniel
> >
> >
> > On Wed, Jul 17, 2013 at 10:19 AM, Daniel Watrous
> > <[email protected]>wrote:
> >
> > > I think I'm getting it now. The Form needs to be embedded in a
> > > panel for the type of inclusion that I'm interested in.
> > >
> > > I created a CnavFormPanel.java and changed CnavForm.html to
> > > CnavFormPanel.html. I left CnavForm.java alone.
> > >
> > > In CnavModify.java I removed this
> > >
> > > Form form = new CnavForm("cnavFormArea");
> > > add(form);
> > >
> > > And added this
> > >
> > > add(new CnavFormPanel("cnavFormArea"));
> > >
> > > That works. Thanks for your help.
> > >
> > > Daniel
> > >
> > >
> > > On Wed, Jul 17, 2013 at 10:07 AM, Daniel Watrous
> > <[email protected]>wrote:
> > >
> > >> I can make it work if I put the markup from CnavForm.html
> > >> directly into CnavModify, but the form is not as reusable then. I
> > >> would have to duplicate the markup for other pages that use the same
form...
> > >>
> > >> Dnaiel
> > >>
> > >>
> > >> On Wed, Jul 17, 2013 at 9:55 AM, Daniel Watrous
> > <[email protected]>wrote:
> > >>
> > >>> That's what I tried to do. I created CnavForm.java and
> > >>> CnavForm.html. In the latter file I have this
> > >>> <wicket:panel>
> > >>> <form wicket:id="cnavForm"...>
> > >>> // form details
> > >>> </form>
> > >>> </wicket:panel>
> > >>>
> > >>> Then I have CnavModify.java and CnavModify.html. You already see
> > >>> what I have in CnavModify.java from my last email. My
> > >>> CnavModify.html
> > has this.
> > >>> <wicket:extend>
> > >>> <span wicket:id="cnavFormArea">Here's the form</span>
> > >>> </wicket:extend>
> > >>>
> > >>> Rather than render I'm getting this error:
> > >>> Last cause: Component [cnavFormArea] (path = [0:cnavFormArea])
> > >>> must be applied to a tag of type [form], not: '<span
> > wicket:id="cnavFormArea"
> > >>> id="cnavFormArea3">' (line 0, column 0)
> > >>>
> > >>> I'll keep trying and report back when I figure it out.
> > >>>
> > >>> Daniel
> > >>>
> > >>>
> > >>> On Tue, Jul 16, 2013 at 10:50 PM, Paul Bors <[email protected]> wrote:
> > >>>
> > >>>> Wicket is a MVC component driven framework similar to Swing.
> > >>>> In short, what you want to do is create your own Panel with
> > >>>> that form file of yours and add it to another Panel as a child.
> > >>>>
> > >>>> See chapter 4 "Keeping control over HTML" of the Wicket Free
> > >>>> Guide
> at:
> > >>>> http://code.google.com/p/wicket-guide/
> > >>>>
> > >>>> Also available from under the Learn section as the Books link
> > >>>> on the right side navigation section on Wicket's home page at:
> > >>>> http://wicket.apache.org/learn/books/
> > >>>>
> > >>>> ~ Thank you,
> > >>>> Paul Bors
> > >>>>
> > >>>> -----Original Message-----
> > >>>> From: Daniel Watrous [mailto:[email protected]]
> > >>>> Sent: Tuesday, July 16, 2013 7:13 PM
> > >>>> To: [email protected]
> > >>>> Subject: Re: Form questions
> > >>>>
> > >>>> Thanks Paul and Sven. I got the form to work and available in
> > >>>> the onSubmit handler.
> > >>>>
> > >>>> Now I'm interested in splitting the form out into it's one file.
> > >>>> So I created a class that has nothing more than the form, but
> > >>>> I'm not sure how to include this into a page.
> > >>>>
> > >>>> In my class I do this:
> > >>>>
> > >>>> public class CnavModify extends ConsoleBasePage {
> > >>>>
> > >>>> public CnavModify(PageParameters parameters) {
> > >>>> super(parameters);
> > >>>>
> > >>>> Form form = new CnavForm("cnavFormArea");
> > >>>> add(form);
> > >>>> }
> > >>>> }
> > >>>>
> > >>>> My CnavModify obviously extends a base page. What do I put
> > >>>> inside the <wicket:extend> tag to have the form render?
> > >>>>
> > >>>> Daniel
> > >>>>
> > >>>>
> > >>>> On Tue, Jul 16, 2013 at 12:00 AM, Sven Meier <[email protected]>
> wrote:
> > >>>>
> > >>>> > Hi,
> > >>>> >
> > >>>> >
> > >>>> > Some problems I can't figure out. The code to create the
> > >>>> > button complains
> > >>>> >> that it requires a CnavUrl but gets back a String.
> > >>>> >>
> > >>>> >> add(new Button("publish", model) {
> > >>>> >> @Override
> > >>>> >> public void onSubmit() {
> > >>>> >> CnavUrl cnavUrl = (CnavUrl) getModelObject();
> > >>>> >> System.out.println("publish");
> > >>>> >> }
> > >>>> >> });
> > >>>> >>
> > >>>> >
> > >>>> > a Button always has a IModel<String> to fill the value attribute.
> > >>>> > Note that in #onSubmit() you're getting the model object of
> > >>>> > the button, not of your form.
> > >>>> > You can write:
> > >>>> >
> > >>>> > add(new Button("publish", model) {
> > >>>> >> @Override
> > >>>> >> public void onSubmit() {
> > >>>> >> CnavUrl cnavUrl = (CnavUrl)
> > >>>> MyForm.this.getModelObject();
> > >>>> >> System.out.println("publish");
> > >>>> >> }
> > >>>> >> });
> > >>>> >>
> > >>>> >
> > >>>> > Using generic types in your code should help you.
> > >>>> >
> > >>>> > Sven
> > >>>> >
> > >>>> >
> > >>>> >
> > >>>> > On 07/15/2013 11:41 PM, Daniel Watrous wrote:
> > >>>> >
> > >>>> >> Hello,
> > >>>> >>
> > >>>> >> I'm interested in creating a single Form that will
> > >>>> >> accommodate the following use cases
> > >>>> >> 1) display blank for creating new records
> > >>>> >> 2) pre-populate for editing existing records
> > >>>> >> 3) map submitted values on to an existing domain object
> > >>>> >> 4) accommodate two actions, Save Draft -or- Publish
> > >>>> >>
> > >>>> >> I'm following Wicket in Action and within my Form
> > >>>> >> constructor I create my model, like this
> > >>>> >>
> > >>>> >> CnavUrl cnavUrl = new BasicCnavUrl();
> > >>>> >> IModel model = new Model((Serializable) cnavUrl);
> > >>>> >> setModel(model);
> > >>>> >>
> > >>>> >> I then use PropertyModel
> > >>>> >>
> > >>>> >> add(new TextField("url", new PropertyModel(cnavUrl,
> > >>>> >> "url")));
> > >>>> >>
> > >>>> >> For the two actions, I'm creating the Button objects like
> > >>>> >> this
> > >>>> >>
> > >>>> >> add(new Button("publish", model) {
> > >>>> >> @Override
> > >>>> >> public void onSubmit() {
> > >>>> >> CnavUrl cnavUrl = (CnavUrl) getModelObject();
> > >>>> >> System.out.println("publish");
> > >>>> >> }
> > >>>> >> });
> > >>>> >>
> > >>>> >> Some problems I can't figure out. The code to create the
> > >>>> >> button complains that it requires a CnavUrl but gets back a
> String.
> > >>>> >>
> > >>>> >> It seems that a new BasicCnavUrl is created once with the Form.
> > >>>> >> What happens on subsequent calls? Can I always expect my
> > >>>> >> model to have the data from the current form submission?
> > >>>> >>
> > >>>> >> Is there a best way to incorporate the idea of an edit,
> > >>>> >> where the model is pre-populated from a data source and
> > >>>> >> pre-fills the Form
> > >>>> fields?
> > >>>> >>
> > >>>> >> Thanks,
> > >>>> >> Daniel
> > >>>> >>
> > >>>> >>
> > >>>> >
> > >>>> > ------------------------------**-----------------------------
> > >>>> > -*
> > >>>> > *-
> > >>>> > -----
> > >>>> > --- To unsubscribe, e-mail:
> > >>>> > users-unsubscribe@wicket.**apache.org
> > >>>> <[email protected].
> > >>>> > org> For additional commands, e-mail:
> > >>>> > org> [email protected]
> > >>>> >
> > >>>> >
> > >>>>
> > >>>>
> > >>>> ---------------------------------------------------------------
> > >>>> --
> > >>>> --
> > >>>> -- To unsubscribe, e-mail: [email protected]
> > >>>> For additional commands, e-mail: [email protected]
> > >>>>
> > >>>>
> > >>>
> > >>
> > >
> >
> >
> > --------------------------------------------------------------------
> > - To unsubscribe, e-mail: [email protected]
> > For additional commands, e-mail: [email protected]
> >
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]