I have a gsp template, where the data for create view is passed through the controller.
def create = {
def bookInstance = new Book()
bookInstance .properties = params
def map = getDefaultValues()
render(template: "create", model: [bookInstance : bookInstance ,
title: map.title,
somelist: somelist
....])
the gsp template
<g:select optionKey="id" from="${somelist}" name="somelist.id" value="${bookInstance ?.somelist?.id}" noSelection="['null': '']"></g:select>
now, in the save method, if there is an error, it returns currently populated and validated instance (default scaffold implementation)
render(template: "create", model: [bookInstance : bookInstance ])
But the fields in the gsp (error page rendered from save action) is empty. I could see the reason as it looks the value in "${somelist}" , but it is not used in save method. Do i just need to check for null in the gsp and use whichever map is available, or any better method (passing all the map in the save method is not an option) ..
thanks in advance..
I figured it out.. I have to pass the same map as was in the create closure .. the reason why we were passing the maps in create is because we wanted to override the default list.. the populated values in bookInstance is only used to preserve the user selection, but not all the values..
Related
I'm a newbie trying to find uses for Neo4J on Grails.
Basically, I've made 20 grocery item nodes through the Neo4J browser and I want to create a simple Grails site that will let users search a grocery item and visually show the items related to it.
My index.gsp has:
<input id="item" />
My viz.js has:
$('#item').keyup(function() {
var item = $('#item').val();
My Item Domain class has
class Item {
static mapWith = "neo4j"
String name
My ItemController class has:
def index() {
def item = Item.list() [item:item] //No idea, just trying out whatever i find :(
and a query with something like:
def query = Item.cypherStatic ("""start n=node({Item}) match (n)-[r]->(x) where r='partner' return n, x)
Questions:
How can I properly send the JS 'item' variable into the ItemController?
How can I use the 'item' variable to properly query the node names which have a 'partner' relationship with the item?
in addition to Motilals answers, you definetly need a wrapping form with an action that points your controller
like
<g:form controller="itemController" action="index" >
<input type="text" id="item" name="item" value="" />
<input type="submit" value="submit" >
</g:form>
then on clicking submit the for will call your index action and there you could parse the value with
def item = params.item
but it looks more like you want some asynchronous stuff right after keyup-function, therefore you could do sth like this :
$('#item').keyup(function() {
var item = $('#item').val();
$.ajax({
url: "${createLink(controller:'itemController', action:'index')}",
data:"&item="+item
})
.done(function( data ) {
console.log(data)
});
});
in this case, you need to pay attention what your index-action is returning, so you can do in the .done() whatever you want with the response.
also note, that when you name an action "index" it will be available at
.../myproject/item/index
or, and thats important
.../myproject/item/
so if your index method requires the data from the input, it will miss them if a user has gone straight to that url
so your index action would rather render the page with the input
and you define another action for executing your query based on input and returning data
set the item to hidden field and then you can access it directly in your controller using params
here you go:
//in index.gsp add below hidden field and set the hidden filed in your js code
<g:hiddenField name="item" value="" />
$('#item').keyup(function() {
var item = $('#item').val();
//in your controller
def index() {
def item = params.item
print item // you see the value for item
//do your stuff
}
once you have item value you could directly use HQL query or use the domain instance
hope this helps you
Regards
Motilal
I have table in UI which is populated by values from database. Now I want to call a controller action Onclick of table row and render to different view.
I tried following code function is getting executed properly but its not rendering to different view.
In GSP:
<tr onclick="<g:remoteFunction controller="LeaveApplied" action='getLeaveDetail' id='${it.id}'/>">
controller:
def getLeaveDetails(){
def leaveObj = leaveAppliedService.getLeaveDetail(params.id)
println "leave: "+leaveObj
render(view:'respond', model: [leave:leaveObj])
}
Any Answers will be thank full.
if you want to update your table with an ajax call, you can try this:
GSP:
onclick="<g:remoteFunction controller="LeaveApplied" action="getLeaveDetail" params="[id: it.id]" update="target_div" />"
Controller:
def getLeaveDetails(){
def leaveObj = leaveAppliedService.getLeaveDetail(params.id)
render(template:'respond', model: [leave:leaveObj])
}
Haven't tested the code, but the important things are to set the params and update Attributes in your GSP and to render a template instead of a view.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Grails populating a domain instance
I am wanting to pass a childInstance object from my view to the controller at the moment I am doing this
<g:formRemote url="[action: 'updateStatus']" update="messages" name="updateStatusForm" onSuccess="document.updateStatusForm.message.value='';">
the updateStatus method is as follows
def updateStatus(String message) {
def status = new Post(message: params.message, author: lookupPerson())
System.out.println("status: " + status.message + " : " + status.author)
status.save(flush: true, failOnError: true)
def messages = currentUserTimeline()
render template: 'profileMessages', collection: messages, var: 'profileMessage'
}
I want to add a childInstance from my view to the updateStatus. But I also want to to work if I don't pass the childInstance to the update Status.
I hope this makes sense.
You cannot pass object instance as request parameter to the controller. Request parameters are strings. So, you can pass something like object ID as a parameter and then load this object by ID in the controller.
Add this to the url
url="[action: 'updateStatus' params:[id:'obj.id']]"
and call it in your controller method with
object = Obj.get(params.id)
My controller is the folowing:
def participated = {
def temp = ConferenceUser.get(params.temp)
def prizes = Prizes.findAllByConferenceUser(temp) // find all rooms where current computer is
def subms = Submissions.findAllByConferenceUser(temp) // find all rooms where current computer is
[temp: temp, priz: prizes, subm: subms]
}
But somehow, when I successfully update a conference value, I wanna go back to the initial page (participated) but I don't know how to pass back the params.temp. (if I do a simple redirect, as the controller is expecting params.temp, it will give me an error because I cannot search prizes with a null object as parameter. So, imagine my update controller is the following:
def update = {
def saveParamshere = params.temp
...
...
(code here)
...
...
redirect(action: "participated", params: [temp: saveParamshere])
}
This code isn't working. How can I successfully go back to my main page and pass in params.temp ?
I think the problem may be, that you are calling update action by submitting form (I suppose). Maybe you are not passing temp value from that form? You can do it by embedding temp as hidden input field into form, or apply it to url by param attribute on form tag.
Using hidden field it might be something like this (in your view file):
<g:form controller="somecontroller" action="update">
(...)
<g:hiddenField name="temp" value="${temp}" />
(...)
</g:form>
Using params attribute:
<g:form controller="somecontroller" action="update" params="[temp : temp]">
(...)
</g:form>
I didn't test any of these so there might be some issues, especially in the second approach.
You could put the params in the flash scope, which lives for two requests, or put them in the session and retrieve them that way.
Here is a link to the grails docs on usage of flash scope:
Grails - Controllers - Controller Scopes
I want to get value of sec:loggedInUserInfo and attempt into a variable named user.
My code looks like this:
<sec:loggedInUserInfo field="username" />
<%
def user = *value of field loggedInUserInfo *
%>
Is it possible for doing that?
This is simpler and works fine for me:
<g:set var="user" value="${sec.username()}" />
To assign any field of the UserDetails instance referred to by <sec:loggedInUserInfo> to a variable you can use:
<g:set var="fullName" value="${sec.loggedInUserInfo(field:'fullName')}" />
(see also Custom User Details)
If you want the user object in the gsp, just pass it back as part of the model map from the controller. in a controller action do
def user = springSecurityService.getCurrentUser()
render view: 'yourgsp', model: [user: user]
I am not sure if we can use that tag directly, I couldn't find it earlier, so I have made my custom tag for this purpose
<m:userName id="${session.SPRING_SECURITY_CONTEXT?.authentication?.principal?.id}"/>
def userName = { attrs ->
Long id = attrs['id'] ? attrs['id'].toLong() : null
User user = User?.get(id);
out << user?.firstName
}
I have created one taglib as loggedinUser which is added on gsp page as :
Welcome <g:loggedInUser/> !
Which is showing logged In username on top of each gsp in my project. In custom tag library my code is as follows :
def springSecurityService
def loggedInUser={
if(springSecurityService.getPrincipal().equals("anonymousUser")){
response.sendRedirect("${request.contextPath}/login/auth")
}else{
out <<"${springSecurityService.currentUser.username}"
out << """ [${link(controller:"logout"){"Logout"}}]"""
}
}
So it's showing on each page as : Welcome USERNAME[Logout] !