Setting domain class property values with GORM - grails

After a user creates a record in my Grails application it takes that information and populates and displays a graph. The user can then click a button on that page and be redirected to the create page. When that happens I would like the previous data entered to be displayed as the defaults for those fields.
In my controller right now we instantiate the domain class.
def create() {
[apiInstance: new Api(params)]
}
Let's say the Api class contains two properties, a string called name and an integer called myValue.
What do I need to do to show the latest values of name and myValue in the database as the new defaults for the fields in the create page?

It sounds like you just want to display each field's value?
<g:textField name="name" value="${apiInstance.name}" />
<g:textField name="myValue" value="${apiInstance.myValue}" />
If you want to display the last created Api by default, you have to get that in your controller. You can use last() to get the last created instance of a domain class.
def create() {
[apiInstance: Api.last() ?: new Api(params)]
}

Related

connect two gsp screens to three domains in grails

so I am working on a web app when the users click on create on the list screen, it takes them to a page where they have to enter some information and then they click on "next" and it will take them to another gsp page where they have to enter data for two domains but none of the data are stored yet in the tables but when they click on "create" button, everything get stored in the database
I was looking for examples but couldnt find any.
I know how to call the record and edit it since all the domains or the tables share id number so I can use it to retrive data. but my problem is when I transfer from the first gsp screen to another I want to save the instance and then when the users click on create, data goes to the three tables
any idea how to do that? I am still beginner and trying to learn
thank you
It sounds kind confusing what you wanna do and I am not sure I completely understood. Because you want to change the whole page, and yet, not to lose those previous answers, right?. Is there a specific reason why you want to do this?
I believe you could sent all the information from the first gsp to a controller and save everything in the "session" (e.g session.name = params.name, session.age = params.age), redirect/render the other gsp and later on, you get the info back from the session plus the info that just came and save everything. This is probably not a very good solution, but this is the only way I figured this out.
:)
Just an idea, I haven't used it until now, but I will some day in the future to modify the dialog-flow in my current application...:
Wouldn't that be a good example for the webflow-plugin?
This is what command objects are used for. Any time you have a collection of data that you want to collect in a form and then "generate" multiple domain objects from, then this is the way.
The idea is to create a single class that has all the information that you want to collect on the form. You post the filled form data back to the controller save action which then validates that the data is complete using the command object constraints. Once you are happy with everything, you then use the data in the command object to create/update your domain objects.
We consider the use of command objects a Grails best practice. You can provide custom validation support in the command object that looks for and validates relationships in the data that are difficult to do with the domain objects. We often write factory methods in the command class that produce a new or updated domain object, making it very convenient for unit testing.
See the "Command Objects" section of the "Web Layer" in the manual for details. In Grails 2, command objects are classes with the #Validateable annotation and in Grails 3 they implement the Validateable trait. If you declare your command class as an inner class in the controller, then it is automatically validateable. We've found that we prefer to declare them in src/groovy rather than as inner classes because they are easier for someone unfamiliar with the code to find.
So amongst all of these answers you have your answer but in all honesty I think it is well beyond your own comprehension at this point.
Assuming you have this example as a form
http://code.runnable.com/UevQr3zfd_oaAAGn/jquery-ui-tabs
On tab 1 you have
Name
Age
On tab 2 you have
Address
Postcode
Then you have two domain class
Class User {
String name
String age
Address address
}
Class Address {
String address1
String postcode
}
So a user has name age and also binded to address, whilst address has address1 and postcode
now your controller action
def save(MyBean bean) {
Address address = new Address(bean.loadAddress()).save()
User user = new User()
def userMap = bean.loadUser()
user.age=userMap.age
user.name=userMap.name
//The above object that got saved first
user.addresss=address
user.save()
render "hopefully this should have saved it as expected"
}
In src/main/groovy/yourPackage/MyBean.groovy
package yourPackage
import grails.validation.Validateable
Class MyBean implements Validateable{
String name
String age
Address address
String address1
String postcode
//Now declare your constraints like your domainClass add validator where required to add additional verification/validation to your objects sent back
//This will return all the objects required as a map to save address domain class
protected Map loadAddress() {
Map results=[:]
results.with {
address1=address1
postcode=postcode
}
return results
}
//this will return the user object
protected Map loadUser() {
Map results=[:]
results.with {
name=name
age=age
}
}
}
Other fairly complex validation bean examples:
PhotosBean CustomerChatBean ScheduleBaseBean
Other points of reference:
As I say I think as a beginner this may take you a while to get your head around but hoping with what is provided it will become a lot clearer now
E2A
It is really complicated!! can I have two gsp screens instead of jquery tabs
That doesn't make much sense.
You can have two actions which one just passes params onto 2nd gsp ?
So
def TestController {
def index() {
render view: page1
}
//where page 1 is the first form and submits to action2
//action2 picks up parmas from page1
def action2() {
render view: page2, model:[params:params]
}
}
in page2.gsp you have
<g:form action="action3">
<g:hiddenField name="originalName" value="${params.originalValue}"/>
<g:hiddenField name="originalName2" value="${params.originalValue2}"/>
<g:hiddenField name="originalName3" value="${params.originalValue3}"/>
Then your actual form content
The problem with doing this this way, is does action2 need to verify params received from page1 ? if so it needs to either render original page or page2 depending.
Once submitted to page2 the hiddenFields can be tampered with by end user so what was validated may be invalid now. You will need some form of a way of revalidating all those again.
Using validation methods above you could just call the validate() functions or maybe build some md5 check of initial values vs what is now sent from page2.
Either way if you don't care about validation and just want to see it work then above is the simplest way.
can I have two gsp screens instead of jquery tabs
in page1 you can just do <g:include action="page2"> and include a 2nd gsp within first but in all honesty page 1 could have just contained both actions in 1 page. which is why it don't make sense

Getting object type after serialization in groovy/grails

Hey guys I would appreciate it if you could help me. First of all excuse my English and secondly I would try my best to describe the problem.
As far as I know after a submitToRemote in grails the form parameters are serialized and then submitted. Now the problem:
Between two GSP pages I'm trying to send an ArrayList<foo> back and forth. To save it on each page I'm using <g:hiddenField> which is then used in the controller using params. When the the form is submitted the controller can no longer use the arrayList because it is of type string.
Also I am to do this without using cookies or sessions.
Any ideas as to how to convert to de-serialize the arrayList after the submit.
Assuming that's a simple ArrayList<Integer> you can use the method list() of params.
def myList = params.list('myList') //myList is the name in the view.
If it's a more complex list, like a list of one domain class, then you need to use commands.
Class A {
String name
}
Class ACommand {
List<A> listA = ListUtils.lazyList( [], FactoryUtils.instantiateFactory(A) )
}
View
<g:hiddenField name="listA[0].name" value="Fisrt Name" />
<g:hiddenField name="listA[1].name" value="Second Name" />
Binding the Command
class MyController {
def someAction() {
//in this example assume that this action is called in the submit of the form
ACommand command = new ACommand()
bindData(command, params) //this will populate the command with your list
}
}

Grails - How to fine tweak events/actions?

I'm very new to Grails so pardon me, what I want to do may be very obvious to others. It will help me understand Grails and how the underlying magic works (or not work). Answers must be in Groovy/Grails, no javascript since I understand how javascript works.
Say I have the files:
User.groovy
UserController.groovy
I'm using scaffolding to CRUD the records in the USER table. Now I want to tweak it a bit.
in file User.groovy:
class User {
String name
static constraints = {
name blank: false
}
}
I want UserController.groovy(Is this the file I should edit?) to check if the submitted username is Bill, then automatically replace username with William then continue to create record in database.
In the web form I type in the name field: Bill and click SUBMIT
After the database is updated, I check the record and the username should be William in the USER table database.
Question #1 (Basic) How can I do this?
Now for something a bit trickier, what if after the William record is created in db#1, and I want to connect to a different db#2 and insert William in the USER table there?
So when I click SUBMIT once, both records will be inserted in 2 different databases almost simultaneously? What this action would do is insert the record in db#1 then connect to db#2 and then do the same insert in serial.
Question #2 (Intermediate) Where do I look in the Grails folders/files to modify this action behavior?
You have to create view which is associated with your controller. In that view, you have to create form, that will enable users to enter username, something like this:
<g:form controller="user" action="save">
<g:textField name="username"/>
<g:submitButton name="save" value="save"/>
</g:form>
Now when user sumbits the form, save action of user controller is invoked. All parameters that where passed to controller action is being held in params map. So in your save action, you can access username like this:
def save = {
def user = new User(username: params.username)
// OR
def user = new User(params)
// you can change username like so
user.username = "William"
user.save()
}
This is very quick example, I advise you to study documentation and some tutorials maybe which will give you more knowledge of all the concepts and tools that Grails provides for you.
With writing user to two databases there is a slight problem. Grails doesn't provide ability to have multiple databases connected to your app out of the box. There is a plugin, called Datasources which allows you to define multiple data sources in your application, but the drawback is that you have to define which domain classes are connected to which data source. Thus you can't have a user domain class for your primary database and secondary, you have to create two domain classes, one for each data source.
I'll just answer the basic :)
Yup, you can do it in UserController.groovy. Say, you have this form:
<g:form action="someAction" method="post">
<input type="text" name="name" ... />
...
</g:form>
In the controller, you can have an action like this (there are multiple possible approaches):
def someAction = {
def nameVar = params.name // get the text this way
// process nameVar here
}
As for the database access... depends how you want to approach it. Grails suggests that you do something like:
User theUser = //get the user
theUser.name = //the value
theUser.save(flush:true)
However, I've encountered time and again some issues with Hibernate so I don't always use that approach. Instead, I do the usual Java-like programming like:
...
theUser.executeUpdate("UPDATE <table_name> ...")
theUser.save(flush: true)
...
Then just select from the database
...
User.executeQuery("SELECT ...")
...
Hope this helps ;)
For Q#1 you should modify the save function in your controller. There you can check the parameters for a specific username or modify the new created user object as you like.
For Q#2 i reccomend you to have a look at the Datasources plugin
Q1: This is really a job for GORM Hibernate events as it involves business logic constraint for you domain.
beforeInsert(){
this.name = "William"
}
Q2: Using multiple data sources is integrated in Grails 2.0. No need for the plugin.

Model Binding to Multiple Types with Same Property Names

I have a view that contains 2 list boxes: Audience & Locale
I'm trying to submit a form that contains the selected index of both to my controller, which has an action method of this signature:
public JsonResult Submit(Audience aud, Locale loc)
{
// do stuff
}
The problem I'm having is both Audience & Locale have an ID property, so the Model Binder is a little bit confused over which to assign the selected values to. Both get assigned the value '1', when Audience should have '2' and Locale should have '1'
The question is how can I get the page to differentiate between the two when it's submitting? We've tried prepending the ID value for Locale with "locale.", so the parameter string that gets passed as data to the Controller looks like
"&locale.id=1&audience.id=2" but that doesn't seem to work.
Any suggestions? If more info is needed, I'll supply it.
Thanks
Dave
Use:
public JsonResult Submit([Bind(Prefix = "audience")]Audience aud,[Bind(Prefix = "locale")]Locale loc)
{
// do stuff
}
Every Audience field should have "audience" prefix in name in html field: audience.id,audience.name,...
<input id="audience_name" name="audience.Name" type="text" value="" />
You should have a specific ViewModel for taking data into your Submit Action. That object should have AudienceId and LocaleId. When you create your dropdowns you should create them with names that match what you expect.

ASP.Net MVC - Passing selected data from View to Controller (Help!)

I have a model (entity class) Newsletter. I pass a list of Newsletter to a View and display the list of Newsletter in a table with each Newsletter across a row. Besides each Newsletter row, there is a checkbox. I will select the Newsletters that I want to send by checking the checkbox and clicking on a send button.
How can I pass the selected Newsletters to the controller?
Thanks.
In your view:
<input type="checkbox" name="newsletterIds" value="<%=newsletter.Id%>"/>
In your target controller:
public ActionResult SendNewsletters(int[] newsletterIds)
{
... do something with the ids...
}
Do something like this in your view:
<%= Html.CheckBox("cbNewColors", true) %><label for="cbNewColors">New colors</label>
in your controller, do something like this:
bool bChecked = form["cbNewColors"].Contains("true");
Simply add a boolean value called Selected to your entity class which, when passed back to the controller, will tell the controller which newsletters were selected in your list.
If you don't want to "pollute" your entity class with client metadata, you could inherit from it and add the selected bool in your derived class.
Alternatively your model can simply contain a separate list that holds references to selected newsletters or some unique identifier with which individual newsletters can later be selected from an original list.
You'll have to do some manual work, since MVC adds hidden fields for each checkbox, and relies on the model binder to deal with the value true,false coming in from the form submission (if the box was checked).
Assuming you have unique IDs available in your views, I'd recommend the following:
Manually create the checkboxes (i.e. don't use the Html helper) with the same name
< input type="checkbox" name="newsletters" value="nl_[id]" id="nl_[id]" />[name]< /label>
Accept a string[] newsletters parameter into your action that handles the post. (You may need to accept a string, and then split it on commas, I don't remember array newslettersArray = newsletters.Split(','); ;)
Convert the string into a list of newsletter IDs doing something like this:
var ids = newsletters.Select(n => int.Parse(n.Substring(2)).ToList();

Resources