Can CRUD forms be used without a CRUD controller?

Asked by Michael Grove

I am wondering if I can re-use the form generation from the CRUD stuff to build create & edit forms for my domain objects without having the rest of the CRUD stuff.

What i'd like in my application is the user goes to /data/12345 and they get the page for the item with id 12345 (this works). And then if they go to /data/12345/edit they get the edit form for that item. I'd like to generate this from the CRUD stuff if possible. Similarly, if they go to /data/new they get a create form, again hopefully generated with the CRUD stuff.

I just don't want the overhead of having a separate "admin" area for this functionality.

Can the CRUD bits be re-used or configured like this?

Thanks.

Question information

Language:
English Edit question
Status:
Solved
For:
play framework Edit question
Assignee:
No assignee Edit question
Solved by:
Michael Grove
Solved:
Last query:
Last reply:
Revision history for this message
Michael Grove (mike-clarkparsia) said :
#1

In my attempts to see if I can get this going, I'm getting this error:

Execution error occured in template /modules/crud/app/views/tags/crud/form.html. Exception raised was NullPointerException : Cannot invoke method getField() on null object.

Which comes from this line in form.html:

%{ def field = _caller.type.getField(fieldName) }%

This is the contents of my template that when I went to it in my browser caused the error:

#{extends 'main.html' /}

<h1>Edit: ${data.getTitle()}</h1>

#{form @save()}
 #{crud.form fields: ['title', 'description', 'releaseDate', 'updateDate']}
 #{/crud.form}
 <p class="crudButtons">
  <input type="submit" name="_save" value="&{'crud.save', type.modelName}" />
  <input type="submit" name="_saveAndContinue" value="&{'crud.saveAndContinue', type.modelName}" />
  <input type="submit" name="_saveAndAddAnother" value="&{'crud.saveAndAddAnother', type.modelName}" />
 </p>
#{/form}

The object 'data' comes in from the edit method of the controller, which just sticks the appropriate object into the renderArgs so it's accessible in the template. The controller, for now, extends the CRUD controller, and uses the CRUD.For annotation to associate it with the model.

I am a bit out into the weeds here, so any pointers in the right direction would be appreciated =)

Revision history for this message
Guillaume Bort (guillaume-bort) said :
#2

Yes you can reuse only part of the CRUD.

For example, if you don't want to use the default show action, you can
write a CRUD Datas controller like this:

public class Datas extends CRUD {

    public static void show(Long id) {
        Data data = Data.findById(id);
        render(data);
    }

}

On Thu, Aug 20, 2009 at 9:56 PM, Michael
Grove<email address hidden> wrote:
> New question #80555 on play framework:
> https://answers.launchpad.net/play/+question/80555
>
> I am wondering if I can re-use the form generation from the CRUD stuff to build create & edit forms for my domain objects without having the rest of the CRUD stuff.
>
> What i'd like in my application is the user goes to /data/12345 and they get the page for the item with id 12345 (this works).  And then if they go to /data/12345/edit they get the edit form for that item.  I'd like to generate this from the CRUD stuff if possible.  Similarly, if they go to /data/new they get a create form, again hopefully generated with the CRUD stuff.
>
> I just don't want the overhead of having a separate "admin" area for this functionality.
>
> Can the CRUD bits be re-used or configured like this?
>
> Thanks.
>
> --
> You received this question notification because you are a member of play
> framework developers, which is an answer contact for play framework.
>

Revision history for this message
Michael Grove (mike-clarkparsia) said :
#3

I'm sorry if I'm being dense, I'm new to Play!, but I don't see how that code snippet allows me to re-use the CRUD based create & edit forms (and validation) or how it solves the error that I'm getting (see my follow-up post with some example code).

I don't think I want to use *any* of the default CRUD actions. I want my own routes to go to my own templates, and I'd like my templates to inherit/use the CRUD forms and validation in order to manage the creation and editing of my data.

I'm trying to avoid having a separate "admin" area. Does the CRUD stuff have to go through admin, ie /admin/data/12345/edit? I need it to be /data/12345/edit. If I can get the CRUD stuff using my site template and going to those URL's instead of the default, that'd probably be ok too. Whatever the best solution is.

Thanks.

Revision history for this message
Guillaume Bort (guillaume-bort) said :
#4

In fact if you look at modules/crud/app/controllers/CRUD.java, you
will see that the show action add 2 objects to the template. The type
object contains informations needed to build the form.

I think you need to do something like;

public static edit(Long id) {
     Data object = ... // retrieve your object here
     ObjectType type = ObjectType.get(getControllerClass());
     render(object, type);
}

That's right that all this stuff is not easily customizable right now.
But I think I could help you to make it work.

By the way, could we continue this discussion on the Google group ? I
prefer since it will surely interst other people. If you don't have
any google account, you can still join the mailing list sending an
email to <email address hidden>.

On Thu, Aug 20, 2009 at 10:21 PM, Michael
Grove<email address hidden> wrote:
> Question #80555 on play framework changed:
> https://answers.launchpad.net/play/+question/80555
>
> Michael Grove gave more information on the question:
> In my attempts to see if I can get this going, I'm getting this error:
>
> Execution error occured in template
> /modules/crud/app/views/tags/crud/form.html. Exception raised was
> NullPointerException : Cannot invoke method getField() on null object.
>
> Which comes from this line in form.html:
>
> %{ def field = _caller.type.getField(fieldName) }%
>
> This is the contents of my template that when I went to it in my browser
> caused the error:
>
> #{extends 'main.html' /}
>
> <h1>Edit: ${data.getTitle()}</h1>
>
> #{form @save()}
>        #{crud.form fields: ['title', 'description', 'releaseDate', 'updateDate']}
>        #{/crud.form}
>        <p class="crudButtons">
>                <input type="submit" name="_save" value="&{'crud.save', type.modelName}" />
>                <input type="submit" name="_saveAndContinue" value="&{'crud.saveAndContinue', type.modelName}" />
>                <input type="submit" name="_saveAndAddAnother" value="&{'crud.saveAndAddAnother', type.modelName}" />
>        </p>
> #{/form}
>
> The object 'data' comes in from the edit method of the controller, which
> just sticks the appropriate object into the renderArgs so it's
> accessible in the template.  The controller, for now, extends the CRUD
> controller, and uses the CRUD.For annotation to associate it with the
> model.
>
> I am a bit out into the weeds here, so any pointers in the right
> direction would be appreciated =)
>
> --
> You received this question notification because you are a member of play
> framework developers, which is an answer contact for play framework.
>

Revision history for this message
Guillaume Bort (guillaume-bort) said :
#5

That's weird because each action do the same :

ObjectType type = ObjectType.get(getControllerClass());

It should be factorised to a before intercepter in the CRUD controller.

@Before
static void addType() {
      type = ObjectType.get(getControllerClass());
      renderArgs.put("type", type);
}

Thats way even if you subclass it, it should work as a charm.

On Thu, Aug 20, 2009 at 10:53 PM, Guillaume
Bort<email address hidden> wrote:
> In fact if you look at modules/crud/app/controllers/CRUD.java, you
> will see that the show action add 2 objects to the template. The type
> object contains informations needed to build the form.
>
> I think you need to do something like;
>
> public static edit(Long id) {
>     Data object = ... // retrieve your object here
>     ObjectType type = ObjectType.get(getControllerClass());
>     render(object, type);
> }
>
> That's right that all this stuff is not easily customizable right now.
> But I think I could help you to make it work.
>
> By the way, could we continue this discussion on the Google group ? I
> prefer since it will surely interst other people. If you don't have
> any google account, you can still join the mailing list sending an
> email to <email address hidden>.
>
>
> On Thu, Aug 20, 2009 at 10:21 PM, Michael
> Grove<email address hidden> wrote:
>> Question #80555 on play framework changed:
>> https://answers.launchpad.net/play/+question/80555
>>
>> Michael Grove gave more information on the question:
>> In my attempts to see if I can get this going, I'm getting this error:
>>
>> Execution error occured in template
>> /modules/crud/app/views/tags/crud/form.html. Exception raised was
>> NullPointerException : Cannot invoke method getField() on null object.
>>
>> Which comes from this line in form.html:
>>
>> %{ def field = _caller.type.getField(fieldName) }%
>>
>> This is the contents of my template that when I went to it in my browser
>> caused the error:
>>
>> #{extends 'main.html' /}
>>
>> <h1>Edit: ${data.getTitle()}</h1>
>>
>> #{form @save()}
>>        #{crud.form fields: ['title', 'description', 'releaseDate', 'updateDate']}
>>        #{/crud.form}
>>        <p class="crudButtons">
>>                <input type="submit" name="_save" value="&{'crud.save', type.modelName}" />
>>                <input type="submit" name="_saveAndContinue" value="&{'crud.saveAndContinue', type.modelName}" />
>>                <input type="submit" name="_saveAndAddAnother" value="&{'crud.saveAndAddAnother', type.modelName}" />
>>        </p>
>> #{/form}
>>
>> The object 'data' comes in from the edit method of the controller, which
>> just sticks the appropriate object into the renderArgs so it's
>> accessible in the template.  The controller, for now, extends the CRUD
>> controller, and uses the CRUD.For annotation to associate it with the
>> model.
>>
>> I am a bit out into the weeds here, so any pointers in the right
>> direction would be appreciated =)
>>
>> --
>> You received this question notification because you are a member of play
>> framework developers, which is an answer contact for play framework.
>>
>

Revision history for this message
Guillaume Bort (guillaume-bort) said :
#6

The default routing is totally optional.

You can replace:
# Import CRUD routes
* /admin module:crud

by:
* / module:crud

Or even don't import the default CRUD routes at all, and define your own routes.

On Thu, Aug 20, 2009 at 10:55 PM, Michael
Grove<email address hidden> wrote:
> Question #80555 on play framework changed:
> https://answers.launchpad.net/play/+question/80555
>
>    Status: Answered => Open
>
> Michael Grove is still having a problem:
> I'm sorry if I'm being dense, I'm new to Play!, but I don't see how that
> code snippet allows me to re-use the CRUD based create & edit forms (and
> validation) or how it solves the error that I'm getting (see my follow-
> up post with some example code).
>
> I don't think I want to use *any* of the default CRUD actions.  I want
> my own routes to go to my own templates, and I'd like my templates to
> inherit/use the CRUD forms and validation in order to manage the
> creation and editing of my data.
>
> I'm trying to avoid having a separate "admin" area.  Does the CRUD stuff
> have to go through admin, ie /admin/data/12345/edit?  I need it to be
> /data/12345/edit.  If I can get the CRUD stuff using my site template
> and going to those URL's instead of the default, that'd probably be ok
> too.  Whatever the best solution is.
>
> Thanks.
>
> --
> You received this question notification because you are a member of play
> framework developers, which is an answer contact for play framework.
>

Revision history for this message
Michael Grove (mike-clarkparsia) said :
#7

Ok, first, yes, we can take this over to google groups. Should I re-ask the question there? Or just make a new post and include the URL to this thread?

Next, I'm using the 1.0 stable 6. I grepped through the source but didnt see the addType method where type is pushed into the renderArgs. Could have missed it, but that might be a difference.

I'd love the help, and to help out, in making this stuff more customizable. I appreciate the help.

I'll move this over to google groups?

Revision history for this message
Guillaume Bort (guillaume-bort) said :
#8

Don't care, just post a link to the original question.

The problem with CRUD is that half of the work is made by the CRUD
actions, not by the templates (at least for the validation part). I
try to make a little simple sample to show you how you could customize
it.

On Thu, Aug 20, 2009 at 11:12 PM, Michael
Grove<email address hidden> wrote:
> Question #80555 on play framework changed:
> https://answers.launchpad.net/play/+question/80555
>
>    Status: Answered => Solved
>
> Michael Grove confirmed that the question is solved:
> Ok, first, yes, we can take this over to google groups.  Should I re-ask
> the question there?  Or just make a new post and include the URL to this
> thread?
>
> Next, I'm using the 1.0 stable 6.  I grepped through the source but
> didnt see the addType method where type is pushed into the renderArgs.
> Could have missed it, but that might be a difference.
>
> I'd love the help, and to help out, in making this stuff more
> customizable.  I appreciate the help.
>
> I'll move this over to google groups?
>
> --
> You received this question notification because you are a member of play
> framework developers, which is an answer contact for play framework.
>