Can CRUD forms be used without a CRUD controller

567 views
Skip to first unread message

mhgrove

unread,
Aug 20, 2009, 5:16:34 PM8/20/09
to play-framework
Just moving the discussion from [1] over to here as requested by
Guillaume.

The basic overview is that I'm trying to customize the CRUD stuff a
little bit, I really only want to pull in the create and edit forms
that it provides and get them seamlessly linked into the rest of my
application.

As Guillaume suggested, I'm going to dig a little into the CRUD module
code and hopefully come with some questions that are a little more
concrete, but I was running into an odd error, there is some example
code and the error messaged provided at the link to the initial
discussion on Launchpad.

Thanks.

[1] https://answers.launchpad.net/play/+question/80555

Guillaume Bort

unread,
Aug 20, 2009, 5:40:06 PM8/20/09
to play-fr...@googlegroups.com, mi...@clarkparsia.com
Thank mike.

By the way I send you a simple example application that hack the CRUD module.
Hope that will help.

That's not perfect but I think it could be a good start for your problem.
Can you move to the trunk ? I released the 1.0 RC1 preview today and
just fixed the type problem in the CRUD controller in the r539.
hack-crud.zip

Guillaume Bort

unread,
Aug 20, 2009, 6:11:12 PM8/20/09
to play-fr...@googlegroups.com, mi...@clarkparsia.com
Well,

Basically my previous sample was really a hack. Digging more into the
CRUD module I really understood what your need was. That's right that
it should be possible to reuse only the CRUD form without relying onto
the CRUD controllers at all.

I hacked a little to make this possible. It's not yet perfect because
the #{crud.form /} tag assume that you have 2 variables (object and
type) available in the template. It would be better if you could do
whatever you want and call the form tag this way:

#{crud.form class:'models.Data' /} for creation and #{crud.form
object:data /} for edition.

I will continue to refactor this tag to allow that. For now here a
second example that should be a better match for your need (work with
the r540).

++ Guillaume.
hack-crud2.zip

Guillaume Bort

unread,
Aug 20, 2009, 6:45:24 PM8/20/09
to play-fr...@googlegroups.com, mi...@clarkparsia.com
Ok, so

To finish I finally made the modification I just said. Using the r541
you can now use the #{crud.form /} tag outside of any CRUD controller.
You don't have anymore to digg yourself with the ObjectType or name
your object variable 'object' ...

#{crud.form class:'models.User' /} to display a creation form of the User class.
#{curd.form object:anyUser /} to display the edition form of any existing user.

That should work the way you expected it, and that's a good thing to
have fixed before the 1.0 release.

I send a latest sample.

++ Guillaume.
crud3.zip

Michael Grove

unread,
Aug 21, 2009, 7:33:03 AM8/21/09
to Guillaume Bort, play-fr...@googlegroups.com

On Aug 20, 2009, at 6:45 PM, Guillaume Bort wrote:

> Ok, so
>
> To finish I finally made the modification I just said. Using the r541
> you can now use the #{crud.form /} tag outside of any CRUD controller.
> You don't have anymore to digg yourself with the ObjectType or name
> your object variable 'object' ...
>
> #{crud.form class:'models.User' /} to display a creation form of the
> User class.
> #{curd.form object:anyUser /} to display the edition form of any
> existing user.
>
> That should work the way you expected it, and that's a good thing to
> have fixed before the 1.0 release.
>
> I send a latest sample.

Wow, that's awesome. Thanks so much for all that work. Let me go
grab r541 and try this out, this is great!

Thanks.

Mike

Guillaume Bort

unread,
Aug 21, 2009, 7:47:56 AM8/21/09
to Michael Grove, play-fr...@googlegroups.com
You can find binary builds here: http://www.playframework.org/download/nightly/
But following the bazaar branch is easy too.

'bzr co lp:play' just works.

Michael Grove

unread,
Aug 21, 2009, 10:15:30 AM8/21/09
to Guillaume Bort, play-fr...@googlegroups.com
So far so good! I was able to get edit/save/create/delete stuff
working exactly as I had planned to do it, the changes you made were
perfect.

I do have one question/issue. I initially could not get anything
showing up in the forms. I eventually tracked this down to the fact
that my Model implementation had all its member variable declared as
private and I wrote the getters and setters for them by hand. I
believe that Play! will generate these if you make the vars public,
but I think at some point I might be adding additional logic to some
of the getters and setters, so I wrote the stubs for them from the
beginning so I would not have to worry about it later. I thought if
you did that (wrote your own getters & setters), Play! just used those
rather than generating ones and you got the same behavior.

Is this the intended design, or a bug? I did find a use for this
behavior, there are properties on the Model we don't want showing up
in the form, so we can hide them by making them private, but access
them by providing our own getters and setters, but then the code is a
mish-mash of the two different styles. If it's a bug, what's the
intended way to hide properties you don't want the user editing?

Thanks for all the excellent work on this.

Cheers,

Mike

On Aug 20, 2009, at 6:45 PM, Guillaume Bort wrote:

> <crud3.zip>

Guillaume Bort

unread,
Aug 21, 2009, 10:50:30 AM8/21/09
to Michael Grove, play-fr...@googlegroups.com
Well, if you look at the ObjectType class, it scans only public Fields:

for (Field f : entityClass.getFields()) {
...
}

I could change that by using getDeclaringFields(), but it would ignore
inherited fields ... Or use both and do a marge ... I'm not sure what
is the best solution but I will not change that for now because we are
in the 1.0 release process and it would change the way that existing
applications work.

----

In fact you can let your fields public even if you define your own
getter/setter.
Play will always use the defined getter or setter if exists. Look at this code:

@Entity
public class Data extends Model {

@Required
public String value;
public Integer anotherValue;

public Integer getAnotherValue() {
if(anotherValue == null) {
return 0;
}
return anotherValue;
}

public void setAnotherValue(Integer value) {
if(value == null) {
this.anotherValue = null;
} else {
this.anotherValue = value * 2;
}
}

public String toString() {
return value + " - " + anotherValue;
}

}

From another class, you can try:

Data data = new Data();
data.anotherValue = null;
assert data.anotherValue == 0;
data.anotherValue = 4
assert data.anotherValue == 8;

And you can try with my crud3 sample, all the generated forms will
work using getter/setter for the anotherValue field.
It is more the way that Scala works than the classic Java standard ...

----

To hide some fields from the generated forms, you can either make them
private, or define your own fields lists in the #{crud.form /} :

#{crud.form fields:['value'] /}

Or to make some fields read only:

#{crud.form}
#{crud.custom 'anotherValue'}
${object.anotherValue}
#{/crud.custom}
#{/crud.form}

Guillaume ++

Michael Grove

unread,
Aug 21, 2009, 10:54:42 AM8/21/09
to Guillaume Bort, play-fr...@googlegroups.com
Ah, ok. Thanks for the clarification regarding how the fields are
pulled down. I had drawn the wrong inference about the getter/setter
methods, your example clears that up for me, and makes sense for what
I had in mind.

Also, thanks for pointing out the custom field lists for the forms,
that's exactly what I was hoping for.

Cheers,

Mike
Reply all
Reply to author
Forward
0 new messages