g:form doesn't seem to have a "controller" attribute - grails

Recently I began to study Grails, and I noticed that the file create.groovy is generated by a dynamic scaffold. The form tag doesn't have an attribute called controller, only action.
So my question is, how does the Grails framework discover the controller that should be called?
<g:form action="save">
<fieldset class="form">
<f:field bean="categoria" property="nome" class="form-control" />
</fieldset>
<fieldset class="buttons">
<g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" />
</fieldset>
</g:form>
Thanks, and sorry for my bad english!

Grails uses "convention over configuration" so whenever you use a form without controller, grails will use the default convention.
Since your view is put in a folder named after a controller, grails will assume that the default controller for any view inside that folder is the one that matches with the folder name. Example
BookController is the default controller for any gsp inside the grails-app/views/book folder.
*This convention also applies to things like links.

Related

Grails - how to call a controller method from a form

I'm completely new to grails, and I appreciate any help.
This code is in my gsp file:
<g:form action="backfillMachineTags">
<fieldset class="buttons">
<g:submitButton name="create" class="save"
value="${message(code: 'default.button.create.label', default: 'Create')}"/>
</fieldset>
</g:form>
And this code is in my RegressionPoolMachineController.groovy file:
def backfillMachineTags()
{
flash.message = "testing message"
redirect(action: "list")
}
But when I click the submit button on the form, the method is never entered and I get a 404 not found.
message:/pool-manager/regressionPoolMachine/backfillMachineTags
status: The requested resource is not available.
I also tried doing:
<g:form url="[action:'backfillMachineTags',controller:'RegressionPoolMachineController']">
but get a similar 404 not found.
Am I missing a step to connect my form and controller?
Try to use the following:
<g:form controller = "controllerName" action ="actionName" >
<fieldset class="buttons">
<g:submitButton name="create" class="save" value ="${message(code: 'default.button.create.label', default: 'Create')}"/>
</fieldset>
</g:form>
Try adding a "controller" attribute to your form in addition to the "action" attribute. You could use url instead of controller and action, but you would need something like
url="${createLink(controller: "myController", action: "myAction")}" instead of what you've shown here.
For reference: http://docs.grails.org/2.5.6/ref/Tags/form.html
You can also look at the generated HTML in your browser (just view source) and see what is actually being generated on the resulting web page. That's usually pretty helpful for finding out why things aren't going where you want them to!

how to render a response to a specific place on a gsp grails

I am new to grails and groovy.
I am trying to find out how to render a response from an action in a grails controller IN THE SAME gsp - but in a DIFFERENT SECTION OF THE gsp - as the gsp that takes the request (in this case a web form gsp page)?
any links or turorials or just straight to the point "do this" kind of replies are welcomed.
I tried to google search for it, but I was not sure what to use as a search term and I could not find a concise answer.
========= UPDATE TO QUESTION (INCLUDING SOME CODE) =========
Here is the code I am working with. It is a Grails application in which I am using a bootstrap template (available for free on the internet of course).
Now the actual code itself for functionality works. What I am having an issue with is this:
I have a gsp page that uses a css template and another gsp temlate for layout. I can start the page as inside the gsp+css tempate using this code (snippet) in my gsp page:
<g:layoutBody/>
This allows me to call my calling controller code in this gsp file for the request:
<body>
<g:form name="form" controller="apiStart" id="form">
<div><g:select name="protocolType" value="restCall" from="${["-select-", "GET", "POST", "PUT", "DELETE"]}"/> &nbsp <label>URL: </label><g:textField name="url" value="${url}" />
&nbsp <label>username: </label><g:textField name="userName" value="${userName}" /> &nbsp <label>password: </label><g:textField name="passWord" value="${passWord}" /></div>
%{--<div class="text-field"><label>URL: </label><g:textField name="url" value="${url}" /></div>--}%
%{--<div class="text-field"><label>username: </label><g:textField name="userName" value="${userName}" /></div>
<div class="text-field"><label>password: </label><g:textField name="passWord" value="${passWord}" /></div>--}%
<br>
<div><label>Use Advanced Parameters?</label><g:checkBox name="useAdvParms" value="${false}" /></div>
<div class="text-field"><label>Header1: </label><g:textField name="header1" value="${header1}" /> &nbsp <label>Value1: </label><g:textField name="value1" value="${header2}" /></div>
%{--<div class="text-field"><label>Value1: </label><g:textField name="value1" value="${header2}" /></div>--}%
<div class="text-field"><label>Header2: </label><g:textField name="header2" value="${header3}" /> &nbsp <label>Value2: </label><g:textField name="value2" value="${header4}" /></div>
%{--<div class="text-field"><label>Value2: </label><g:textField name="value2" value="${header4}" /></div>--}%
<br>
<div class="submit"><g:actionSubmit value="Submit" action="save"/></div>
</g:form>
</body>
And then this gsp code for the response:
<body>
<h3>API Test Results</h3>
API Tested: ${apiStart.url}, Response: ${apiStart.response3}
<br>
%{--<g:textArea name="myField" value="myValue" rows="20" cols="100"/>--}%
<div class="textarea"><label>Output</label><br><g:textArea name="myField" value="${apiStart.result3}" />
</div>
%{--Responce Code: ${apiStart.response3}<br>--}%
%{--Response: <br> ${apiStart.result3} <br>--}%
</body>
My issue: it works fine as separate pages. I want to render the results of the request on the same page as the calling request.
in the screen shot attached: I want to put the results in the text box where it says "Output Displayed here...."
I assumed templates in grails is the way to go about it. but I get a Java Null pointer exception when I try to insert the template into that part of the code.
Can someone advise and show me the best way to do this?
==================== END of Updated question ===================
thanks.
ironmantis7x
You can try using Grails templates.
Basically Template is a (reusable) part of a View.
Info:
So you create template file bookTemplate.gsp, put all the gsp/html code in there as usual (but just the part, if it will be used in the body, then don't add html, body, head tags etc.
Example:
<div class="book" id="${book?.id}">
<div>Title: ${book?.title}</div>
<div>Author: ${book?.author?.name}</div>
</div>
Then you render that template into the gsp page in places where you want them to be (with a simple grails render tag. And it will simply get compiled (as the code from template would be pasted into gsp view).
Render:
<g:render template="bookTemplate" model="[book: myBook]" />
I don't know your grails version, but on 2.4.5, and maybe on your version, you can use :
http://docs.grails.org/2.4.x/ref/Tags/submitToRemote.html
And have a look to the attribute update :
update (optional) - Either a Map containing the elements to update for
'success' or 'failure' states, or a string with the element id to
update, in which case failure events would be ignored
And you also can trigger javascript on some events, ...
In your action called in the submitToRemote button, you can render a template (but do not put your layout in this template if you render a template, otherwise you will have all you website structure rendered...) and it will be displayed in the HTML element with the ID that you have put in "update" property.
The example given in the link is interesting.

Grails default methods in controller

I am having a problem saving a domain instance in grails; The domainInstance that's passed to the default update method in my controller is NULL. The GSP page I am submitting from is not the default edit page. I have certain values from DB that need to be saved. I have the form tag defined on the page that contains the values I need to submit, as follows.
<g:form id="sampleForm" url="[resource:domainInstance, controller:'cntrlrName', action:'update']" method="PUT" >
I also have a version field which looks like this.
<g:hiddenField name="version" value="${domainInstance?.version}" />
My g:submit is as follows
<g:actionSubmit action="update" value="${message(code: 'default.button.update.label', default: 'Update')}" />
Why is my domain instance null? What am I missing?
This is the common mistake one could make. The attribute id in <g:form> tag is not the id attribute of HTML tags but it is the id to use in the link for default mapping of Grails i.e.
"/$controller/$action/$id" {}
So change your tag as:
<g:form name="sampleForm" id="${domainInstance.id}" controller="cntrlrName" action="update" method="PUT">
You can pass the domainInstance but I feel it is better practice to pass the id instead of the object. Try passing the id of the domain instance and then reading the object in the controller.
<g:form name="sampleForm" action="action" controller="controller" id="${domainInstance.id}" ></g:form>
// in controller
def resource = Domain.read(params.id)
another approach could be to pass the domainInstance as a hiddenField
<g:hiddenField name="resource" value="$domainInstance" />

displaying bean class items on view - beginner

The bean class looks like this:
String houseNo
String address
Person person
The view looks like this
<g:form action="save">
<fieldset class="form">
<g:render template="form" />
</fieldset>
<fieldset class="buttons">
<g:submitButton name="create" class="save"
value="${message(code: 'default.button.create.label', default: 'Create')}" />
</fieldset>
</g:form>
According to my knowledge in Grails, i think is <g:render template="form" /> will pull all form attributes and display it.
But what i want to do is Instead of displaying a drop-down for Person, i want to display all Person related fields like personName, personAge. How can i display these fields in a label underneath ?
Help
You're correct about the way g:render works, the template part refers to a GSP which will look through the bean values and print them according to the html + groovy markup in "_form.gsp" (located in your views folder under the controller name).
To change the way the Person domain object is displayed, simply edit this "_form.gsp" and take out the 'select' html code - replacing it with groovy markup using the property values of the bean, eg.
${beanName.person.personName} //(use the existing code to help workout the bean name etc)
Hopefully that helps you on your way.

Controller of Grails

Hi All,
I have an edit button
<span class="button"><g:actionSubmit class="edit" action="edit" value="${message(code: 'default.button.edit.label', default: 'Edit')}" /></span>
But when click on it the adderess on the browser was not http:\...\edit,
it was http:\...\index. Why?
I tried to delete or rename the name of Edit in controller, it still not influence. Why?
Thanks!!!
Try specifying controller's name with g:form like
<g:form controller="CONTROLLER_NAME">

Resources