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>;
I am trying to find the way to expand a JavaScript variable value in HTML.
I know that it is possible to do it in PHP, like this:
<?php
$myString = "Hello World";
?>
<p><?=$myString?></p>
Is it possible to do likewise in JavaScript with a similar native inline tag?
Note
I am aware of other solutions such as calling other functions, which is exactly what I want to avoid.
There is no native way for injecting JavaScript values into HTML by just using a tag like the PHP <=? tag. What comes closest might be ES6 template literals.
It can look like this:
var mystring = 'Hello World';
document.write(`
<p>${mystring}</p>
<div>
some other stuff
</div>
`);
This version of JavaScript is available in most browsers today, but will of course not work in older browser versions, nor for current Internet Explorer versions (are we surprised?) -- but it works in Edge.
There are no native capabilities in HTML that allow injection of JavaScript values following the PHP-like syntax. In my opinion, the above comes as close as you can get. The only way to access to JavaScript variables from within HTML is with specific attributes (like "onclick") -- which serve another purpose --, and with script tags, which do not work like the <?= PHP tag either, but more like the standard <?php tag.
Using templating libraries might be an option (e.g. mustache, underscore, EJS, handlerbars, pug, plates, dust.js, hogan.js, jsrender, markupjs, nunjucks...).
A simple, poor man's template library - class/content based
The above listed templating engines offer advanced features, but here is a very basic implementation that understands this kind of HTML:
<span class="template">`I want to say "${mystring}"`</span>
When the page loads, the "poor man's library" should render that as:
<span>I want to say "Hello World"</span>
Here is the code for doing just that:
/* my simple template library: you would include this from another JS file */
document.addEventListener("DOMContentLoaded", function(event) {
var templates = document.getElementsByClassName('template');
[].forEach.call(templates, function (template) {
template.textContent = eval(template.textContent);
template.setAttribute('class', '');
});
});
/* my set of variables */
var mystring = 'Hello World';
# my simple template CSS
.template {display: none};
<span class="template">`I want to say "${mystring}"`</span>
A simple, poor man's template library - attribute based
Here is variation on the same concept. Now the syntax is a custom tag inject of which the value attribute has the value to inject. Here it is the "library" that injects the template literal backticks. This could also have been done in the first version.
/* my simple template library: you would include this from another JS file */
document.addEventListener("DOMContentLoaded", function(event) {
var templates = document.getElementsByTagName('inject');
[].forEach.call(templates, function (template) {
template.textContent = eval('`' + template.getAttribute('value') + '`');
template.removeAttribute('value');
});
});
/* my set of variables */
var mystring = 'Hello World';
<inject value='I want to say "${mystring}"' />
I don't see how it's possible to achieve in JavaScript what you're trying to achieve.
The closest thing I can think of, is something like this :
<script>var message = "Hello World";</script>
<div>Before message</div>
<div>
<script>document.write(message);</script>
</div>
<div>After message</div>
It is, however, recommended to avoid using document.write!
Note
Based on the info you provided in the comments, I think you're looking for one of the following approaches :
Replace your Twig templates with Mustache templates, for which both an official PHP implementation and an official JavaScript implementation exist.
Use an (unofficial) port of Twig to JavaScript to process your Twig templates in JavaScript.
I typically set up jquery templates in my html files like this:
<script id="some-template" type="text/x-jquery-tmpl">
my template contents go here... with some data: {data}
</script>
then my javascript that needs to use this template would look for it by the id and pass in the needed data:
var template = $("#some-template");
var html = template.tmpl({data: "data goes here..."});
// do something with the 'html' var, like attach it to the DOM
now i'm trying to write jasmine-bdd specs for my javascript. i don't see anything particularly wrong with the way i set up my templates and have my javascript find / expand the template... but i'm not sure how to get jasmine to play nice with this... so...
how can i use jasmine to test my javascript, when my javascript relies on a jquery-template, and the template is defined in my html page directly?
do i have to duplicate my template in a jasmine-jquery fixture? or is there a way to make a jasmine-jquery fixture use my existing html / template definition?
in case anyone is interested, here's how i solved this: http://lostechies.com/derickbailey/2011/09/06/test-driving-backbone-views-with-jquery-templates-the-jasmine-gem-and-jasmine-jquery/
I need to include a JavaScript object (JSON) in my HTML page.
JSON is rendered at the same time page HTML is rendered on server. Data is not retrieved using AJAX call.
I can think of two ways of doing this, and looking for feedback and recommendations.
What are good practices for passing JavaScript (JSON) blob with a page?
Option 1
HTML:
<script type='text/javascript'>
var model = { <JSON> };
</script>
.js:
function doSomething() { <use this.model here> }
Option 2
HTML:
<script type='text/javascript'>
loadModel({<JSON>});
</script>
.js (included at the top of the html file):
var model = null;
function loadModel(model) { this.model = model; }
function doSomething() { <use this.model here> }
Variation
Instead of including JSON in HTML, JSON can be stored in a separate .js file. Any comments on doing so?
Option 1 lets you include .js file anywhere, and including it at the bottom of the page makes it render faster (good thing), but since JavaScript renders the model on the page, this makes it a moot point. Still not depending on the location of the .js inclusion makes it less error prone.
Also R# complains (reasonably) about model being uninitialized.
Option 2 feels better (it encapsulate details better, for one), but .js must be included before call to loadModel.
I have seen and done both ways, but didn't notice any significant advantages of one way over the other.
Server platform should be irrelevant, but it is IIS 7.5/ASP.NET MVC 3/Razor
Forget your two suggestions - both are extremely vulnerable to XSS. NEVER PUT UNTRUSTED TEXT IN A SCRIPT TAG.
Instead, use the owasp recommendation.
Stick your (HTML encoded) JSON in the DOM like so:
<div id="init_data" hidden>
<%= html_escape(data.to_json) %>
</div>
Then read it in JavaScript like so:
// external js file
var dataElement = document.getElementById('init_data');
// decode and parse the content of the div
var initData = JSON.parse(dataElement.textContent);
There would be ever so slightly more overhead with option two. As you have the overhead of a function call, and an extra variable (your parameter), which will be allocated and deallocated.
As you said, there is little advantage/disadvantage to either way.
Can you use jQuery? Then you can use the DOM ready event instead of including javascript in your HTML.
EDIT:
Hmm, in that case you could include the JSON inside a hidden element when the page is generated. Then inside the DOM ready event you could read and parse it from the page using jQuery.
Another alternative might be to use HTML 5 data attributes and including the data in one of those.
If it were me I'd probably just use an ajax call since it is easier and seems a little cleaner.
I am a web guy doing mostly Perl server-side stuff, and I'm slowly coming to a few conclusions.
It is far better to do most of your code via Javascript and toss data back and forth via AJAX than it is to hit submit and reload a mostly-identical page
I like jQuery because I like CSS, and it's fun to chain together big long and scary-to-others definitions
There's something to that templating stuff.
You want your HTML elements to look like your HTML elements, and it's easier to define that in HTML:
<div class="sidebar_elem">
TEXT
</div>
Than it is to cobble up the same in Javascript or jQuery:
( '<div/>' )
.attr('id' , 'sidebar_elem' + i )
.addclass( 'sidebar_elem' )
;
( '<a/>' )
.attr('href' , link_url )
.appendTo( '#sidebar_elem' + i )
;
This is to say that I am no longer a templating agnostic, but I don't know which templating tool to believe in. I have looked into some jQuery-based templating plugins, but I have yet to become happy with any of them, in part because the ones I've seen seem to want to put all that code into the page itself, which breaks the "Only markup goes into HTML files, only style goes into CSS files, only code goes into JS files" mantra I keep reciting.
So, I'm looking for a Javascript-based templating tool that would allow me to have my templates in an outside file so I can have one template change cover a series of web pages. If it's jQuery-based, that's great, less stuff I have to learn, but it isn't a deal-breaker.
There are several good ones out there:
Mustache.js
Pure.js
Json Template
If you want a jQuery version, Tempest looks good.
The 2 libs I know that do not mix template coding with HTML markups are chain.js and PURE
chain makes only DOM manipulations.
PURE uses a mix of DOM and innerHTML as the DOM alone can be slow to render bigger templates.
I'm the main contributor of PURE, and we created it to build a web app on the ajax model you describe.
Take a look at this one http://ejohn.org/blog/javascript-micro-templating/. Made by John Resig, creator of jQuery, this one doesn't even need jQuery, and it's freaking small. It also stores templates in script tag (Daniel's answer). Example template:
<script type="text/html" id="user_tmpl">
<% for ( var i = 0; i < users.length; i++ ) { %>
<li><%=users[i].name%></li>
<% } %>
</script>
Maybe you can load them using src attribute if you really need them to be in separate files, which I don't think is a wise idea, because it means additional roundtrip to the server. So at the end, for the sake of optimization, you can store them in separate files, but embed them server side in the page that needs them.
Since there is no well defined API and a best library for templating, I would suggest you choose one that is actively developed. Below, I briefly explained two libraries that are actively being developed.
jQuery team decided that jQuery Templates will no longer be actively developed or maintained, thus I would strongly suggest NOT using it. See this blog entry.
You can use JsRender in accordance with JsViews to take full functionality provided by jQuery Templates and even more like data linking. You can find demos for JsRender and JsViews. I would suggest using these libraries since they are actively being developed by jQuery UI team but be aware that they are still not even beta!
Mustache is another templating solution that is actively being developed and it simplifies templates by combining conditional tags and enumeration tags. It also provides strong features like inverted sections, partials and high order sections with simple syntax. Mustache is also one of the fastest templating solutions See blog by Brian Landau. I, personally, find mustache a good templating solution since it has a simple syntax and performs well.
How about EJS?
Example from their page:
"EJS combines data and a template to produce HTML."
Data:
{title: 'Cleaning Supplies', supplies: ['mop', 'broom', 'duster'] }
Template:
<ul>
<% for(var i=0; i<supplies.length; i++) {%>
<li><%= supplies[i] %></li>
<% } %>
</ul>
Result:
mop
broom
duster
You should check out google closure template. It's completely independent so you can use it with any lib you want. It's a templating tool written in java.
http://code.google.com/closure/templates/docs/helloworld_js.html
It allows you to create a template on the server, run a java "compiler" on it and the output is a javascript function that takes json as its parameter.
{namespace examples}
/**
* Greets a person using "Hello" by default.
* #param name The name of the person.
* #param? greetingWord Optional greeting word to use instead of "Hello".
*/
{template .helloName}
{if not $greetingWord}
Hello {$name}!
{else}
{$greetingWord} {$name}!
{/if}
{/template}
This will generate a function called examples.helloName that can be called like
Their format is very IDE friendly, I get all the HTML syntax highlighting when editing the templates
examples.helloName({name: 'Ana', greetingWord:"Howdy"});
You can call other templates from within templates, it automatically html escapes your data (unless you tell it not to), provides bidirection support.
Another great thing is the fact that the templating tool can also generate java code. So somebody writing an app that must support browsers with scripting disabled can generate the HTML on the server if necessary.
Last but not least, unlike other js templating systems (), the template is parsed on the server, so the client side only has to do the merging of the template and data, the parsing of the template is done as a build step on the server.
http://dev.sencha.com/deploy/dev/docs/?class=Ext.XTemplate is an example of a templating tool that runs completely on the client. There are two problems with this approach, the parsing of the template is done on the client and your html has to be embedded in a javascript string. However, some IDEs (Intellij) will highlight the HTML inside JS strings).
What about JAML Code?
http://github.com/edspencer/jaml
Similar to a few of the above but I believe is a bit more logical...
It is the concept of defining your templates via JSON / JavaScript and then using a function in JavaScript to pass arguments to your template which gets it rendered and returned as an element.
There are implementations around for the various JavaScript Frameworks that exist.
Try out this:
https://www.npmjs.com/package/jlate
use CDN:
<script src="https://cdn.jsdelivr.net/combine/npm/lodash,npm/jlate#0.0.2/jlate/JLate.min.js"></script>
I given below working example where you can replace github template url with your own template sample:
https://raw.githubusercontent.com/webphonix/JLate/main/test_project/template/weblate_loop.html
<div class="row">
<% _.each(names, function(n){ %>
<div class="col-md-6"><%- n.name %></div>
<% }) %>
</div>
var author = [{
name: "Guru"
},
{
name: "Gurudev"
},
{
name: "Test"
},
{
name: "Webphonix"
},
];
$$("#my_temp").jlate({
names: author
});
<script src="https://cdn.jsdelivr.net/combine/npm/lodash,npm/jlate#0.0.2/jlate/JLate.min.js"></script>
<div>
<jlate id="my_temp" src="https://raw.githubusercontent.com/webphonix/JLate/main/test_project/template/weblate_loop.html" type="template">
Loading...
</jlate>
</div>
Try JLate:
https://www.npmjs.com/package/jlate
use version 0.0.2 instead 0.0.1
use below cdn:
<script src="https://cdn.jsdelivr.net/combine/npm/lodash,npm/jlate#0.0.2/jlate/JLate.min.js"></script>
Use a script block.
<script id="someId" type="text/html">
<!-- your template here -->
</script>
and one of many JQuery plugins.
http://weblogs.asp.net/scottgu/archive/2010/05/07/jquery-templates-and-data-linking-and-microsoft-contributing-to-jquery.aspx
I have a templating engine called stencil.js, which I believe is pretty sweet. It works with jQuery via the jquery-haml DOM building engine.
Write your template (which you can put in an external file and decode as JSON):
["%div.sidebar_elem"
["%a", { href: { key:'link' } },
{ key: "text" }
]
]
And run it through stencil along with your data:
$("#parent").stencil(template, { link: "http://example.com", text: "Click me!" });
There are more examples at the stencil.js GitHub project, but I think it's just what you're looking for.
It could use a couple more utility methods, and some code for an unfinished data binding component is still in the master branch, so drop me a comment if you’re interested and I'll see if I can clean it up.
check out ibdom, and some background/history here: Recommended JavaScript HTML template library for JQuery?
Could always go with jQuery-Templates: http://api.jquery.com/category/plugins/templates/
What about http://www.enfusion-framework.org
Stuff like this:
<span template>Our telephone number is {phone}.</span>
<span session>You are logged in as {nickname}.</span>