passing map from grails to javascript - javascript

My problem is passing Map object from grails controller to JavaScript.
I have the following code inside controller
def scoreValue=new HashMap<String,String>();
scoreValue.put("0","poor");
scoreValue.put("1","good");
...
return (view:'viewname',model:[scoreValue:scoreValue]);
I have been searching for solution and have got this link pass a groovy array to javascript code. but could not help.
What I did was change the return statement to
return (view:'viewname',model:[scoreValue:scoreValue as grails.converters.JSON])
and inside gsp view I have the following code.
<g:if test="${scoreValue}">
var scoreValue=${scoreValue};
</g:if>
But what i got inside html page is the following
var scoreValue={"0":"Failure","1":"Poor"}
any help would be appreciated. thanks!

There's actually a few ways of handling GSP encoding. In addition to D. Kossatz's answer, these methods will help you out (see more at mrhaki's excellent Grails Goodness blog)
var scoreValue=${raw(scoreValue)};
var scoreValue=${scoreValue.encodeAsRaw()}
Please be aware that there is an inherent risk of cross-site scripting vulnerabilities when rendering user input unprotected on the page. So long as you know for certain that only you can set that value, and proper safe-checks to ensure it is what it is supposed to be, you should be fine.

Try:
var scoreValue= <g:applyCodec encodeAs="none">${scoreValue}</g:applyCodec>;

Related

Calling controller function from gsp

I need to call a controller function from javascript on my gsp.
I have read different solutions from hundreds of places but none worked.
The problem which I found closest to mine was this.
But I am not repeating the same mistake as this and thus the solution didn't help.
I have a tag like this which calls the javascript function
<g:select name="poNumber" noSelection="['':'Select PO Number']" from="${com.rerq.PurchaseOrder.list()}"
onchange="getProject(this.value)" />
And the javascript function looks like this
function getProject(poNumber){
var projectName = document.getElementById("projectName");
var newData = ${remoteFunction(controller: 'sow', action: 'getProject', params: ['poNumber':poNumber])};
}
And the function I need to call is
def getProject(String poNumber) {
String projectName = Sow.find("from Sow as s where s.poNumber=?", [poNumber])
return projectName
}
The controller function might have mistakes as I am completely new to groovy and grails. But my understanding is that the control isn't reaching here so this should not be the cause of any problem.
I am getting below exception
No signature of method: remoteFunction() is applicable for argument types: (java.util.LinkedHashMap) values: [[controller:sow, action:getProject, params:[poNumber:null]]]
I tried using remoteFunction() in g:select itself but it threw another exception which said
Attribute value quotes not closed ...
even though they were.
Any help is greatly appreciated.
To use remoteFunction with Grails 3 you need to add the ajax-tags plugin: org.grails.plugins:ajax-tags:1.0.0
Actually you can have your gsp recognize some Grails functions inside your js if the script is inside the gsp and anything you need for your js is created on the server side. In your case it seems you want to do an ajax call so you could have the following.
project.gsp (Consider that you already loaded jQuery)
<g:select name="poNumber" noSelection="['':'Select PO Number']" from="${com.impetus.rerq.PurchaseOrder.list()}"
onchange="getProject(this.value)" />
And in the same file you have
<script type="text/javascript">
function getProject(poNumber){
jQuery("#yourTarget").load("${createLink(action: 'getProject')}",{poNumber: poNUmber},function(response, status, xhr ){
if ( status == "error" ) {
alert("No data loaded.")
}
});
}
</script>
As you see a gstring in load("${}",... is used because it will be parsed in the server and at client side your actual js it will parse to load("yourcontrollerName/getProject",..... Why not code the url directly in the js? Because by using createLink() it is less likely to make reference mistakes.
EDIT
If you want to do this but using an external js file, you would need a way to pass the url, to the js, and use a simple load function. So something like this will be helpful
<g:select name="poNumber" noSelection="['':'Select PO Number']" from="${com.impetus.rerq.PurchaseOrder.list()}"
onchange="getProject(this.value, \'${createLink(action:'getProject')}\')" />
Once on the server onchange="getProject(this.value,\'${createLink(action:'getProject')}\')"would be parsed to onchange="getProject(this.value,'yourController/getProject')". Be wary that I might have messed up the ""s and ''s so verify your html output.
And you would need a js function that accepts the uri
function getProject(value, targetUri){
....
}
What you need to review is when is your function needed, on the server o in the client;if the functions are inside a gsp or not; And if not available, how could you pass data to them.
You cannot access grails's controller from javascript. I haven't tested it but this might work.
<g:createLink controller="sow" action="getProject", params="['poNumber':poNumber]"/>
Also, if you use Google Chrome's developer's tool, you will see how your javascript code is displayed. Make sure it is in right syntax.

Injecting data in html with javascript

Using server side scripting it's as easy as pie to inject data in HTML like this (ASP.NET):
//Assuming theTime is a variable
<h1>the time is, #theTime</h1>
But in JavaScript one basically needs to:
Create an element:
<h1></h1>
Give it an ID:
<h1 id="whatever"></h1>
Create a script tag:
<script></script>
Locate the element by it's ID:
document.getElementById("whatever")
Then use innerHTML to modify it's content:
document.getElementById("whatever").innerHTML = "Hi, " + TheTIme;
Final code:
<h1 id="whatever"></h1>
<script>
document.getElementById("whatever").innerHTML = "Hi, " + TheTime;
</script>
Is it possible to inject values/data in JavaScript as one would do in ASP.NET / PHP?
EDIT: The variable is a JS variable and getting it from the server is under control.
Well you could use some template library like handlebars and use jquery to facilitate the element selection, example:
<div id="target"></div>
<script id="hi-template" type="text/x-handlebars-template">
Hi {{userName}}
</script>
<script type='text/javascript'>
var template = Handlebars.compile($("#hi-template").html());
$('#target').html(template({userName: "bob"}));
</script>
Javascript Templating solves exactly this problem of binding data to HTML elements.
Below are few of the common templating engines used these days:
Underscore.js
Handlebars.js
Mustache.js
If you are looking for something simple, try Micro Templating engine from John Resig
<h1>Hi, #theUsersName</h1>
I've never worked with ASP.NET, but I'm assuming #theUserName is a variable. If that's the case, then a 1 to 1 replacement for that is not possible. However, it's still possible.
I'm not sure how you're getting the username, but I would assume you have some way to get it into a JavaScript variable. In that case, I would suggest something like this:
function changeName(username) {
document.getElementById("username").innerHTML = username;
}
<h1>Hi, <span id="username">StackOverflow</span>!</h1>
<button onclick="changeName('user3088260')">Click to Change the Name</button>
Now, getting the data is a different story, I would assume an AJAX call, in which case you could do something like this
if(xmlhttp.responseText !== ""){
changeName("user3088260");
}
All that other stuff you mentioned in unnecessary.
I will also say the entire idea seems like a poor design choice. If you have a username, I would assume you have a login system. If you have a login system, then you have to validate the user before outputting the page. If you have to validate the user before outputting the page, then you have their username. If you have their username, then put it in the pre-rendered page. No need to use JS after you've outputted the page.
Hopefully that is what you're looking for. If not, I'm sure somebody else will be along shortly with something that does.
One of the easiest javascript template engines to get started with is Underscore. Here is a protected answer from SO explaining how to do it:
How to use underscore.js as a template engine?
As someone says, there are a lot of Javascript templating frameworks. Here you have a few of them:
Handlebars.js
mustache.js
Hogan.js
doT.js
nunjucks
jade
After picking one, you can (for example) do something like this:
<h1>Hi, {{userName}}</h1>
You can see an example of client-side templating working with Angular on this link.

Angular JS - How can I sanitize HTML in a controller?

I'm trying to sanitize HTML in the controller as I'm trying to update the document.title dynamically with the title of the post. (I know that for SEO purposes this isn't recommended but I need to use it here)
$scope.prevTitle = "dynamic title gets pulled in here &"
document.title = $scope.prevTitle
For this example, I've just used a random HTML entity. I've tried the parseAsHtml method from the official documentation but I'm having no luck. I tried the following:
document.title = $sce.parseAsHtml($scope.prevTitle)
But no luck. The documentation suggests it needs to be used within a function. Any suggestions on how I would acheive this?
A console log of the above ( console.log($sce.parseAsHtml($scope.prevTitle)) ) would return:
function (b,c){return e.getTrusted(a,d(b,c))}
$sanitize can be used as #acg pointed out. Alternatively, you can use it directly with the ng-bind-html directive where it automatically sanitizes the output variable before rendering the output.
The above point is not quite clear in the documentation, but there is a fairly extensive example in it with which you can play in pluncker.
Please also bear in mind that ngSanitize is an external module and you need to explicitly load angular-sanitize.js or include it in your js minification.
Use $sanitise and trustAsHtml instead
First of all inject 'ngSanitize' in your module
Now in your controller, just add
$scope.prevTitle = "dynamic title gets pulled in here &"
document.title = $sce.trustAsHtml($scope.prevTitle)
If you want to sanitize the html returned, I would think it would be as simple as using the $sanitize service:
document.title = $sanitize($sce.parseAsHtml($scope.prevTitle))

Call a js with GET parameters

I need someone to enlighten me.
I've seen this:
<script src="http://host.com/file.js?no_forms=1"></script>
What does that means? A GET parameter passed to a javascript file?
Into which conditions this can be done?
What kind of approach is this?
Any help would be appreciated.
?no_forms=1 is just a query string parameters. i will just tell the common usage of such things.
Used for to avoid caching (get new updated version of JS)
Some sort of redirection
Even some application usage ideas.
Sometimes the parameter is used simply to prevent client side caching.
It could also be that requesting file.js is actually rewritten as a dynamic call (say script.php?file=file.js&no_forms=1) that is fetching the correct file and using the extra parameter somehow.
You can use this
<script src="http://host.com/file.js" no_forms="1"></script>
And
function $_GET(q,s) {
s = s || window.location.search;
var re = new RegExp('&'+q+'=([^&]*)','i');
return (s=s.replace(/^\?/,'&').match(re)) ? s=s[1] : s='';
}
And get result
var noForms = $_GET('no_forms');

JSP Parsing url and matching key words

Here is my question, I am using jsp script, trying to match a key word in requesting url and do something:
<script>
$url = '${pageContext.request.requestURL}';
if("${fn:contains(url, 'key')}" == true){
...
}
....
But this doest work... I am not sure where the problem is but I want it to be like when url contains this string, go in to the if condition.
Thank you
You are mixing JSP/EL and JavaScript as if they run in sync. This is wrong. JSP/EL runs in webserver and produces HTML code which get executed in webbrowser. JavaScript (JS) is part of the generated HTML code and runs in webbrowser only.
You need to do it either fully in JSP/EL, or fully in JavaScript. You can use JSP/EL to dynamically generate JS code which get later executed when the page arrives at browser. Rightclick page in browser, do View Source to see what JSP/EL has generated. You should not see any line of JSP/EL. You should only see HTML/JS code. It's exactly that JS code which get executed then.
You're using a JSP EL function to test a JS variable which isn't in the variable scope at that moment at all. This is not going to work. It can only test JSP/EL variables.
Here's how you could do it in pure JS:
<script>
var url = window.location.href;
if (url.indexOf('key') > -1) {
// ...
}
</script>
If you really insist in doing it using JSP/EL, you could do as follows:
<script>
var url = '${pageContext.request.requestURI}';
if (${fn:contains(pageContext.request.requestURI, 'key')}) {
// ...
}
</script>
This will then generate the following JS code (rightclick page in browser and View Source to see it):
<script>
var url = '/some/uri';
if (true) {
// ...
}
</script>
But this makes no sense. Whatever functional requirement you need to solve, you need to think twice about the right approach. Feel free to ask a new question about solving the concrete functional requirement the proper way.
If you want a parameter that the page was requested with, use ${param.paramName}. So in this case ${param.key}. See implicit objects in the docs. And if you just want to check it has a value try ${not empty param.key}.

Categories