I require to be able to change the value of a bean (attribute)
passed into a gsp. Am using grails 2.3.11.
see code below - this does not modify the bean - please can you inform how it can be done?
At line #1 this is an attempt to replace the attribute with a new value -
so that Venue -> Xenue.
At line #2 this shows that the value has not changed.
// locns.gsp
<!DOCTYPE html>
<html >
<head>
...
<script type="text/javascript">
<g:each in="${locns}" status="i" var="locn">
var x = '${locn.addr1}'.replace("V", "X");
locn.addr1 = x; #1
</g:each>
</script>
</head>
<body>
<g:each in="${locns}" status="i" var="locn">
${locn.addr1} #2
</g:each>
</body>
</html>
// Controller:
def locns() {
Locn[] locns = new Locns[2];
locns[0] = new Locn();
...
locns[0].addr1 = "Venue Point";
locns[0].addr2 = 'London';
...
[locns:locns]
}
// attribute / bean class
class Locn {
public String addr1;
public String addr2;
...
}
Thank you, Steve.
You should be able to do something like this (even though it is dicouraged and your controller should handle this)
at #1
<g:each in="${locns}" status="i" var="locn">
<% def locnChanged = new ArrayList<>() %>
<% def x = locn %>
<% x.locn = locn.addr.replace("V", "X") %>
<% locnChanged.add(x) %>
</g:each>
at #2
<g:each in="${locnChanged}" status="i" var="locn">
${locn.addr1}
</g:each>
No need for javascript there. But once again, you shouldn't take care of that in the GSP.
You're mixing up client and server side logic here. First, the GSP tags execute on the server side to generate HTML which is sent to the browser, and only then does the generated JavaScript execute in the client browser. The GSP will produce some HTML that looks something like
<!DOCTYPE html>
<html >
<head>
...
<script type="text/javascript">
var x = 'Venue Point'.replace("V", "X");
locn.addr1 = x; #1
var x = 'Venue 2'.replace("V", "X");
locn.addr1 = x; #1
</script>
</head>
<body>
Venue Point #2
Venue 2 #2
</body>
</html>
The JavaScript will then fail with an exception at the first line #1 because you're trying to set a property on an undefined value.
Related
I am using GGTS: 3.6.4,
Grails: 2.4.4
jdk 1.7.51
google-visualization:1.0
I am trying to pass data from a domain class to my view to display a map using the Google Visualization plug-in. I believe I am passing this data to my GSP incorrectly. I can make the data render on screen, in text, in the acceptable format, please see my GSP for def mapData.
When I use
def mapData =[<g:each in="${places}" var="place" status="i">[${place.lat}, ${place.lon}, "${place.name }"],</g:each>]
I get this error:
Message:Attribute value quote wasn't closed (elementId="map" columns= "${mapColumns}" data= "[
Any tips on how I can change my GSP to get the data from my domain class?
Domain Class:
package zmapapp
class ThingLoc {
String name
Float lat
Float lon
static constraints = {
lat()
lon()
name()
}
}
Controller:
package zmapapp
class ThingLocController {
def scaffold = true
def map (){
def places = ThingLoc.list()
[places: places]
}
}
GSP:
<html>
<head>
<title>Google Visualization API plugin</title>
<meta name="layout" content="main" />
<gvisualization:apiImport/>
</head>
<body>
<%
def mapColumns = [['number', 'Lat'], ['number', 'Lon'], ['string', 'Name']]
def mapData = [[37.4232, -122.0853, 'Work'], [37.4289, -122.1697, 'University'], [37.6153, -122.3900, 'Airport'], [37.4422, -122.1731, 'Shopping']]
%>
<script type="text/javascript">
function selectHandler(e) {
alert('A table row was selected');
}
function readyHandler(e) {
console.log('Table is ready');
}
</script>
<h2>See Map Below </h2>
<gvisualization:map elementId="map"
columns= "${mapColumns}"
data= "${mapData}" />
<table cellpadding="2" cellspacing="0">
<td>
Map
</td>
<td>
<div id="map" style="width: 400px; height: 300px"></div>
</td>
</tr>
</table>
[<g:each in="${places}" var="place" status="i">[${place.lat}, ${place.lon}, "${place.name }"],</g:each>]
</body>
I ended up not using the def mapColumns or mapData and instead used the google syntax found here: https://developers.google.com/chart/interactive/docs/gallery/map
here's my update gsp:
<html>
<head>
<title>Dat Map tho</title>
<meta name="layout" content="main" />
<gvisualization:apiImport/>
<script type="text/javascript">
google.load('visualization', '1', { 'packages': ['map'] });
google.setOnLoadCallback(drawMap);
function drawMap() {
var data = google.visualization.arrayToDataTable([
['Lat', 'Long', 'Name'],
<g:each in="${places}" var="place" status="i">[${place.lat}, ${place.lon}, "${place.name }"],</g:each>
]);
var options = { showTip: true };
var map = new google.visualization.Map(document.getElementById('chart_div'));
map.draw(data, options);
};
</script>
</head>
<body>
<div id="chart_div"></div>
<br><br>
Map Visualization Information
</body>
</html>
I want to display the result of sql each row from the service code to my gsp view.
My Service code is:
def health()
{
def schemaList = [:]
groovy.sql.Sql sql = new groovy.sql.Sql(dataSource);
sql.eachRow("SELECT SOURCE, count(1) as COUNT from fact group by SOURCE");
ArrayList returnResults = []
sqlStatement.eachRow(sqlString)
{
returnResults<<it.toRowResults()
}
sqlStatement.close()
return[returnMap:returnResults]
}
My Controller Code is:
def stats = {
def health = AccessLogService.heath()
render (template:'healthview', model:[health:health])
}
My gsp view is as follows:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="layout" content="admin" />
<title>Health</title>
</head>
<body>
<SCRIPT language="JavaScript">
</SCRIPT>
<br />
<br />
<font style='font-size:14px;font-weight:bold;'>Health Condition</font>
<div id='overall'>
<g:if test="${health.size() > 0}">
<table border="1">
<thead>
<tr>
<th>Source</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<g:each in="${health}" status="i" var="thisRecord">
<tr>
<td>${thisRecord.SOURCE}</td>
<td>${thisRecord.COUNT}</td>
</tr>
</g:each>
</tbody>
</table>
</g:if>
</div>
</body>
</html>
I am not able to see the results of my query in gsp view? Where I am going wrong.
you are trying to get the wrong key of your model.
you service returns a hash [returnMap:returnResults] so your controller renders the model: [health:health] -> [health:[returnMap:returnResults]].
thus in your gsp you should refer to health.returnMap to see the list:
<g:if test="${health.returnMap}">
...
<g:each in="${health.returnMap}" status="i" var="thisRecord">
<tr>
<td>${thisRecord.SOURCE}</td>
<td>${thisRecord.COUNT}</td>
</tr>
</g:each>
...
</g:if>
UPDATE:
the code looks strange... this is how it should be:
ArrayList returnResults = []
sql.eachRow("SELECT SOURCE, count(1) as COUNT from fact group by SOURCE"){
returnResults << it.toRowResults()
}
Where is the sqlStatement variable declared in your service? I think that is the error.
And an advice you need to debug your program. for example, Test if the service returns result by:
running your app debug mode
using log.debug
using println
or if you are doing these and have seen any erorrs on your console post that here.
I am using grails mail plugin. When I submit my form, it will send an email from aaa#example.com to textField name="email successfully but how can I send an email with a layout...not blank like this picture http://www.4shared.com/photo/uT2YUCfo/Capture__2_.html or maybe some CSS..
FORM
<g:form action="send">
<table style="width:500px">
<tbody>
<tr>
<td>Your Email Address </td>
<td><g:textField style="width:250px" name = "email"/></td>
</tr>
<tr>
<td>Your Name</td>
<td><g:textField style="width:250px" name = "user"/></td>
</tr>
<tr>
<td><input type="submit"/></td>
</tr>
</tbody>
</table>
</g:form>
MAIL CLOSURE
def send = {
sendMail {
to params.email
from "aaa#yahoo.com"
subject "Test Reset Password"
body(view:"/user/layoutmail",model:[name:params.user])
}
render "Email Terkirim"
}
Well you could actually use a layout for emails, similarly how you would use layouts for view pages. What you would want to do is create a new layout and a view file for your email body content.
Layout: eg. ../views/layouts/emailLayout.gsp
<%# page contentType="text/html" %>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style>
a {color: #348eda;}
</style>
</head>
<body>
<g:layoutBody/>
</body>
</html>
View eg. ../views/emails/welcomeEmail.gsp
<%# page contentType="text/html" %>
<g:applyLayout name="emailLayout">
<html>
<body
Your Welcome ${welcome.username}
</body>
</html>
</g:applyLayout>
And to send the mail heres an example
def sendWelcomeMail(User user, String url){
def rtn = [success:false]
if(user) {
def fooBar = [
username: user.username,
email: user.email,
url: url
]
sendMail {
async true
to fooBar.email.trim()
subject "Welcome Email"
body(view: '/emails/welcomeEmail', model: [welcome: fooBar])
}
rtn.success = true
}
return rtn
}
It isn't going to pick up a grails layout. And you don't really want it to. You should construct your email in a fashion that it could be a stand alone web page with no other dependencies. All the static resources used should be accessible via a public URL.
When I navigate to the page, why is the send() function being called automatically?
I want to be able to view the gsp page, fill in a few text fields, and THEN call the submit with an action of "send"
This is my gsp file
<%# page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<meta name="layout" content="main"/>
<title>Contact Form</title>
</head>
<body>
<g:form name="contactForm" action = "send">
<g:render template = "contactFormFields"/>
<g:actionSubmit value = "submit" action = "send"/>
</g:form>
</body>
</html>
This is the contactFormFields template
<g:select name = 'subject' from = '${EmailService.options}' noSelection='Topic'/>
Contact Name: <g:textField name = "contact"/>
Contact Number: <g:textField name = "phone"/>
Contact Email: <g:textField name = "email"/>
Aditional Information:
<g:textArea name = "information" rows="5" cols="40"/>
EmailServiceController
class EmailServiceController {
def defaultAction = "contactService"
def send() {
sendMail(){
to "mygroovytest#gmail.com"
from params.email
subject params.subject
body params.information
}
}
}
domain class
class EmailService {
static constraints = {
def options = new ArrayList()
options.push("Qestions about service")
options.push("Feedback on performed service")
options.push("Other")
options.push("Why am I doing this")
}
}
gsp that calls the service
<div class="banner">
<h1>My HVAC company</h1>
Contact me today!
Services
Have Me Contact You!
</div>
You don't have a contactService action in your EmailServiceController so it's probably treating send() as the default action when you link to the controller with no action name. Try adding an empty contactService action
def contactService() { }
In my Rails app I've created a set of checkboxes as follows:
<div class="form_row">
<label for="features[]">Features:</label>
<% ['scenarios', 'news', 'role_profiles', 'private_messages', 'chatrooms', 'forums', 'polls'].each do |feature| %>
<br><%= check_box_tag 'features[]', feature, (#features || {}).include?(feature) %>
<%= feature.humanize %>
<% end %>
</div>
I'd like to know how to create a button that would "Select All".
Using jQuery;
<script type="text/javascript">
function selectAll(){
$("input:checkbox").each(function(){
$(this).attr('checked', true);
});
return false;
}
</script>
HTML button:
Select All
If you use the Prototype JS, you might find this blog post helpful. It gives a fairly concise way to perform a select all.
http://www.ryboe.com/2008/07/10/select-all-checkboxes-with-prototype-js.html
In your view you could use the following snippet to create a "Select All" link:
<%= link_to_function("Select All","checkboxes.each(function(e){ e.checked = 1 })") %>
In addition, you'd need the following Javascript code somewhere on the same page (or maybe even abstracted out to the public/javascripts/application.js file
var checkboxes = [];
checkboxes = $$('input').each(function(e){ if(e.type == 'checkbox') checkboxes.push(e) });
var form = $('options'); /* Replace 'options' with the ID of the FORM element */
checkboxes = form.getInputs('checkbox');
Here's the full source of a working example, if this doesn't work you might need to check to make sure your JS libraries are loading properly.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="http://www.google.com/jsapi" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var checkboxes;
google.load("prototype", "1.6");
google.setOnLoadCallback(function(){
checkboxes = [];
checkboxes = $$('input').each(function(e){ if(e.type == 'checkbox') checkboxes.push(e) });
var form = $('options'); /* Replace 'options' with the ID of the FORM element */
checkboxes = form.getInputs('checkbox');
});
</script>
</head>
<body>
<form id="options">
<fieldset><input type="text" value="test"></fieldset>
<fieldset><input type="checkbox" value=0> 0</fieldset>
<fieldset><input type="checkbox" value=1> 1</fieldset>
<fieldset><input type="checkbox" value=2> 2</fieldset>
<fieldset><input type="checkbox" value=3> 3</fieldset>
</form>
Select All
</body>
</html>
I think you can use query like that
<script>
$('#check_all').on("click", function(){
var check = $('input[type="checkbox"]');
check.prop("checked", !check.prop("checked"));
});
</script>
and the html will be something like
<%= button_tag 'select / unselect all', id: 'check_all', class:'b' %>