I have something like this:
Class person {
string name
string status
boolean working
boolean vacation
}
static constraints = {
name()
status(inList: ["Active","Inactive"])
}
What I need is to show the working and vacation fields in the create and edit views, only if Active is selected in status.
I searched and read alot but can't find a way, maybe I'm missing something since I'm new to grails. Any help is appreciated.
Thank you
This can not easily be done with Dynamic scaffolding. You will need to edit the generated views to add the logic in. See the GSP tag refference for if at
http://grails.org/doc/latest/ref/Tags/if.html
In your case something like
<g:if test="$person.active ==true">
Insert GSP code to edit data here.
</g:if>
Related
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
I have two grails domain classes
Class MultipleChoiceQuestion {
String question
static constraints = {
...
}
static hasMany = [options:MultipleChoiceOption]
}
and
class MultipleChoiceOption{
String answerOption
boolean correctOption
MultipleChoiceQuestion question
static constraints = {
...
}
}
I want my users to be able to create a question then add atleast 3 options without navigating/clicking on different screens.
My first question is must I generate view and start editing code?
And if the answer to question above is yes then my second question is, what's the best way to save a question along with multiple options in one form submit?
The generated code will have something like following for each option.
<g:textField name="answerOption" value="${answerOptionInstance?.answerOption}"/>
<g:checkBox name="correctOption" value="${answerOptionInstance?.correctOption}"/>
how can I have multiple such elements in one page?
Please see the wireframe to get an idea of what I want to achieve, my apologies for poorly created wire frame.
Click on the link for opening the image in your browser
http://cynosuredev.com/wf.png
maybe this site will help you
http://omarello.com/2010/08/grails-one-to-many-dynamic-forms/
You don't have to use Grails scaffolding if you don't want to. Since this is a pretty specialized form, you should construct the HTML yourself. I've created a test project at github that shows a good design for this problem. Check it out.
I have a Person class with two properties: name and address. I want to build a GSP page which allows for 10 users to be created at one time. This is how I'm implementing it and was wondering if there is a better way:
First, make 20 text boxes in the GSP page - 10 with someperson.name and 10 with someperson.address field names (make these in a loop or code them all individually, doesn't matter).
Second, process the submitted data in the controller. The someperson object has the submitted data, but in a not-so-nice structure ([name: ['Bob', 'John'], address: ['Address 1', 'Address 2']]), so I call transpose() on this to be able to access name, address pairs.
Then, build a list of Person objects using the pairs obtained from the previous step and validate/save them.
Finally, if validation fails (name cannot be null) then do something... don't know what yet! I'm thinking of passing the collection of Person objects to the GSP where they are iterated using a loop and if hasErrors then show them... Don't know how to highlight the fields which failed validation...
So, is there a better way (I should probably ask WHAT IS the better way)?
You should use Grails' data-binding support by declaring a command object like this
class PersonCommand {
List<Person> people = []
}
If you construct your form so that the request parameters are named like this:
person[0].name=bob
person[0].address=england
person[1].name=john
person[1].address=ireland
The data will be automatically bound to the personCommand argument of this controller action
class MyController {
def savePeople = {PersonCommand personCommand->
}
}
If you call personCommand.validate() it might in turn call validate() on each Person in people (I'm not sure). If it doesn't you can do this yourself by calling
boolean allPersonsValid = personCommand.people.every {it.validate()}
At this point you'll know whether all Person instances are valid. If they are not, you should pass the PersonCommand back to the GSP and you can use the Grails tags:
<g:eachError>
<g:hasErrors>
<g:renderErrors>
to highlight the fields in errors. If you're not exactly sure how to use these tags to do the highlight, I suggest you run grails generate-all for a domain class and look at the GSP code it generates.
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.
in webforms I would always use my masterpage to set page titles and meta description based on the current url. I was thinking of doing the same for my Asp.net Mvc projects but I ain't sure where to start. It would be nice to be able to set the title/description based on the controller and/or action with some default values incase I don't specify any info. The reason why I do this is because I like everything to be in one place because that makes it easy to spot mistakes.
Edit:
After reading the answers and googling some I was thinking it might be cool to get the info from an xml file. With Xml looking something like this:
<website title="default title for webpage">
<controller name="HomeController" title="Default title for home controller">
<action name="Index" title="title for index action" />
</controller>
</website>
I am new to Asp.net Mvc so I am not sure where to initialize this.
I suggest the following strategy:
Create an hierarchy of models:
abstract class MasterModel
{
public string PageTitle { get; set; }
}
abstract class HomeBaseModel : MasterModel
{
PageTitle = "Home";
}
abstract class UsersBaseModel : MasterModel
{
PageTitle = "Users";
}
/************************************/
class HomeNewsModel : HomeBaseModel
{
PageTitle = "News";
}
class UsersProfileModel : UsersBaseModel
{
PageTitle = "Profile";
}
You define a master model to hold the page title and you create base models to hold default titles for a controller. This way, you can define the title in each action explicitly or leave it out so that the default title for this controller will be used.
Then in your master view you just write once:
<title><%= Model.PageTitle %></title>
and it's done.
You could simply pull that data from the master page's Model, then let that Model have some reasonable defaults.
So after a few days of trying stuff I ended up with making a custom filter that reads from a XML file.
I added the code to copypastecode.com
http://www.copypastecode.com/9797/
http://www.copypastecode.com/9809/
http://www.copypastecode.com/9805/
I am very novice at Asp.net Mvc and "real" C# coding so if you see strange stuff please forgive me. If somebody wants to optimize it or has a better solution feel free to post it as an answer.
Next thing I am gonna try is to make it without a filter so it's activated on all controllers. Not sure where to hook up the logic though. So if anybody can push me into the right direction let me know.