How to set the JSTL variable value in java script?
<script>
function function1()
{
var val1 = document.getElementById('userName').value;
<c:set var="user" value=""/> // how do i set val1 here?
}
</script>
How do I set the 'user' variable (JSTL) value from 'val1' (Java script)?
It is not possible because they are executed in different environments (JSP at server side, JavaScript at client side). So they are not executed in the sequence you see in your code.
var val1 = document.getElementById('userName').value;
<c:set var="user" value=""/> // how do i set val1 here?
Here JSTL code is executed at server side and the server sees the JavaScript/Html codes as simple texts. The generated contents from JSTL code (if any) will be rendered in the resulting HTML along with your other JavaScript/HTML codes. Now the browser renders HTML along with executing the Javascript codes. Now remember there is no JSTL code available for the browser.
Now for example,
<script type="text/javascript">
<c:set var="message" value="Hello"/>
var message = '<c:out value="${message}"/>';
</script>
Now for the browser, this content is rendered,
<script type="text/javascript">
var message = 'Hello';
</script>
Hope this helps.
one more approach to use.
first, define the following somewhere on the page:
<div id="valueHolderId">${someValue}</div>
then in JS, just do something similar to
var someValue = $('#valueHolderId').html();
it works great for the cases when all scripts are inside .js files and obviously there is no jstl available
<script ...
function(){
var someJsVar = "<c:out value='${someJstLVarFromBackend}'/>";
}
</script>
This works even if you dont have a hidden/non-hidden input field set somewhere in the jsp.
Just don't. Don't write code with code. Write a JSON object or a var somewhere but for the love of a sensible HTTP divide, don't write JavaScript functions or methods hardcoded with vars/properties provided by JSTL. Generating JSON is cool. It ends there or your UI dev hates you.
Imagine if you had to dig into JavaScript to find something that was setting parameters in the middle of a class that originated on the client-side. It's awful. Pass data back and forth. Handle the data. But don't try to generate actual code.
You have to use the normal string concatenation but you have to make sure the value is a Valid XML string, you will find a good practice to write XML in this source http://oreilly.com/pub/h/2127, or if you like you can use an API in javascript to write XML as helma for example.
This variable can be set using value="${val1}" inside c:set if you have used jquery in your system.
As an answer I say No. You can only get values from jstl to javascript. But u can display the user name using javascript itself.
Best ways are here.
To display user name,
if u have html like
<div id="uName"></div>
You can display user name as follows.
var val1 = document.getElementById('userName').value;
document.getElementById('uName').innerHTML = val1;
To get data from jstl to your javascript :
var userName = '<c:out value="${user}"/>';
here ${user} is the data you get as response(from backend).
Asigning number/array length
var arrayLength = <c:out value="${details.size()}"/>;
Advanced
function advanced(){
var values = new Array();
<c:if test="${empty details.users}">
values.push("No user found");
</c:if>
<c:if test="${!empty details.users}">
<c:forEach var="user" items="${details.users}" varStatus="stat">
values.push("${user.name}");
</c:forEach>
</:c:if>
alert("values[0] "+values[0]);
});
You can save the whole jstl object as a Javascript object by converting the whole object to json. It is possible by Jackson in java.
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonUtil{
public static String toJsonString(Object obj){
ObjectMapper objectMapper = ...; // jackson object mapper
return objectMapper.writeValueAsString(obj);
}
}
/WEB-INF/tags/util-functions.tld:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<tlib-version>1.0</tlib-version>
<uri>http://www.your.url/util-functions</uri>
<function>
<name>toJsonString</name>
<function-class>your.package.JsonUtil</function-class>
<function-signature>java.lang.String toJsonString(java.lang.Object)</function-signature>
</function>
</taglib>
web.xml
<jsp-config>
<tablib>
<taglib-uri>http://www.your.url/util-functions</taglib-uri>
<taglib-location>/WEB-INF/tags/util-functions.tld</taglib-location>
</taglib>
</jsp-confi>
mypage.jsp:
<%# taglib prefix="uf" uri="http://www.your.url/util-functions" %>
<script>
var myJavaScriptObject = JSON.parse('${uf:toJsonString(myJstlObject)}');
</script>
Related
I'm working on a Node.js app (it's a game). In this case, I have some code set up such that when a person visits the index and chooses a room, he gets redirected to the proper room.
Right now, it's being done like this with Express v2.5.8:
server.get("/room/:name/:roomId, function (req, res) {
game = ~databaseLookup~
res.render("board", { gameState : game.gameState });
}
Over in board.ejs I can access the gameState manner with code like this:
<% if (gameState) { %>
<h2>I have a game state!</h2>
<% } %>
Is there a way for me to import this into my JavaScript logic? I want to be able to do something like var gs = ~import ejs gameState~ and then be able to do whatever I want with it--access its variables, print it out to console for verification. Eventually, what I want to do with this gameState is to display the board properly, and to do that I'll need to do things like access the positions of the pieces and then display them properly on the screen.
Thanks!
You could directly inject the gameState variable into javascript on the page.
<% if (gameState) { %>
<h2>I have a game state!</h2>
<script>
var clientGameState = <%= gameState %>
</script>
<% } %>
Another option might be to make an AJAX call back to the server once the page has already loaded, return the gameState JSON, and set clientGameState to the JSON response.
You may also be interested in this: How can I share code between Node.js and the browser?
I had the same problem. I needed to use the data not for just rendering the page, but in my js script. Because the page is just string when rendered, you have to turn the data in a string, then parse it again in js. In my case my data was a JSON array, so:
<script>
var test = '<%- JSON.stringify(sampleJsonData) %>'; // test is now a valid js object
</script>
Single quotes are there to not be mixed with double-quotes of stringify. Also from ejs docs:
"<%- Outputs the unescaped value into the template"
The same can be done for arrays. Just concat the array then split again.
I feel that the below logic is better and it worked for me.
Assume the variable passed to the ejs page is uid, you can have the contents of the div tag or a h tag with the variable passed. You can access the contents of the div or h tag in the script and assign it to a variable.
code sample below : (in ejs)
<script type="text/javascript">
$(document).ready(function() {
var x = $("#uid").html();
alert(x); // now JS variable 'x' has the uid that's passed from the node backend.
});
</script>
<h2 style="display:none;" id="uid"><%=uid %></h2>
In the EJS template:
ex:- testing.ejs
<html>
<!-- content -->
<script>
// stringify the data passed from router to ejs (within the EJS template only)
var parsed_data = <%- JSON.stringify(data) %>
</script>
</html>
In the Server side script:
ex: Router.js
res.render('/testing', {
data: data // any data to be passed to ejs template
});
In the linked js (or jquery) script file:
ex:- script.js
In JavaScript:
console.log(parsed_data)
In JQuery:
$(document).ready(function(){
console.log(parsed_data)
});
Note:
1. user - instead of = in <% %> tag
2. you can't declare or use data passed from router to view directly into the linked javascript or jquery script file directly.
3. declare the <% %> in the EJS template only and use it any linked script file.
I'm not sure but I've found it to be the best practice to use passed data from router to view in a script file or script tag.
This works for me.
// bar chart data
var label = '<%- JSON.stringify(bowlers) %>';
var dataset = '<%- JSON.stringify(data) %>';
var barData = {
labels: JSON.parse(label),
datasets: JSON.parse(dataset)
}
You can assign backend js to front end ejs by making the backend js as a string.
<script>
var testVar = '<%= backEnd_Var%>';
</script>
This should work
res.render("board", { gameState : game.gameState });
in frontend js
const gameState = '<%- JSON.stringify(gameState) %>'
Well, in this case you can simply use input text to get data. It is easy and tested when you use it in firebase.
<input type="text" id="getID" style="display: none" value="<%=id%>">
I know this was answered a long time ago but thought I would add to it since I ran into a similar issue that required a different solution.
Essentially I was trying to access an EJS variable that was an array of JSON objects through javascript logic like so:
<script>
// obj is the ejs variable that contains JSON objects from the backend
var data = '<%= obj %>';
</script>
When I would then try and use forEach() on data I would get errors, which was because '<%= obj %>' provides a string, not an object.
To solve this:
<script>
var data = <%- obj %>;
</script>
After removing the string wrapping and changing to <%- (so as to not escape html going to the buffer) I could access the object and loop through it using forEach()
Suppose you are sending user data from the node server.
app.get("/home",isLoggedIn,(req,res)=>{
res.locals.pageTitle="Home"
res.locals.user=req.user
res.render("home.ejs");
})
And now you can use the 'user' variable in the ejs template. But to use the same value using client-side javascipt. You will have to pass the data to a variable in the tag.
Passing ejs variable to client-side variable:
<script>
let user= '<%- JSON.stringify(user) %>';
</script>
<script>home.js</script>
Now you can access the user variable at home.js
I use this for different languages on our site:
Locale locale2 = (Locale)session.getAttribute("org.apache.struts.action.LOCALE");
ResourceBundle bundle = ResourceBundle.getBundle("content.test.Language", locale2);
I can easy access the string values of the ResourceBundle in HTML to include it on the site via:
<%= bundle.getString("line1") %>
But in some cases I need to access the string values out of javascript.
I have not found a way to do this so far.
I only found a ugly workaround to get the string values.
On the HTML part I include:
<input type="hidden" name="hiddenLine2" id="hiddenLine2" value=<%= bundle.getString("line2") %>>
I do this for all strings I could possibly need.
To access one of them out of javascript I do this:
var line2 = document.getElementById("hiddenLine2").value;
This is working so far, but I donĀ“t like it.
I am sure there could be a better solution.
Some of the possible solutions.
Use an ajax method to get your resource by passing a key.
Use Hidden input fields and load values.
Use a dedicated jsp page to declare js variables or even a js function to get values according to key.
like this.
<script type="text/javascript">
var messageOne = '<%=bundle.getString("line1") %>';
var messageTwo = '<%=bundle.getString("line2") %>';
</script>
It is normally bad practice to use scriplets <% %> inside your jsp files.
You can use the fmt tag from the jstl core library to fetch information from your resource bundles.
<fmt:bundle basename="bundle">
<fmt:message var="variableName" key="bundleKey" />
</fmt:bundle>
<input type="hidden" name="hiddenLine2" id="hiddenLine2" value="${variableName}">
should work
infact, i think you can also directly embed it into the javascript with EL aswell
var line2 = ${variableName}; //instead of getting it from document.getElement(...)
Based on what I have tried, you can use jstl library to print the translated messages directly into JavaScript like:
alert("<fmt:message key='line1'/>");
And if you are using struts2 for handling the locales you can easily define you Bundles getting either the struts2 locale, saved by the i18nInterceptor present on the default stack, or the user request locale (the clients' browser one)
<!-- //Import the requierd libraries -->
<%#taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- //Take the Locale from struts if it's present and from the user request if not -->
<c:set var="locale" value="${not empty sessionScope.WW_TRANS_I18N_LOCALE
? sessionScope.WW_TRANS_I18N_LOCALE : pageContext.request.locale}"/>
<!-- //Get the bundle based on the Locale -->
<fmt:setLocale value="${locale}"/>
<fmt:setBundle basename="content.test.Language"/>
But if you want to be able to extract that JavaScript code into an external .js file on the future I recommend you to use some of the internalionalization libraries available for JavaScript, like Globalize (It's the only one I have used, but there are plenty on the net).
The downside of using an external JavaScript library for internationalization is that you will have to define the tranlation resources directly on .js files, it's impossible to access to your .properties on the server from a client-based language like JavaScript.
Here is a different solution.
Load bundle like OP did, with the method getBundle().
Using the third option on Arun's answer, create a separate JSP file to create a custom JavaScript object.
This is the content of said JSP:
<%#page import="com.tenea.intranet.conf.Conf" %>
<%#page import="java.util.ResourceBundle,
java.util.Enumeration" %>
<script type="text/javascript">
var _get = function(ID){
if (this.hasOwnProperty(ID)) return this[ID];
else {
console.warn("[Resources] Error al obtener clave <"+ ID +">");
return "[ERROR]";
}
};
var _search = function(text){
var elems = { }
Object.keys(this).map(e => {
if (typeof (this[e]) !== "function" && this[e].includes(text)) { elems[e] = this[e]; }
});
return elems;
};
var Resources = {
<%
ResourceBundle labels = ResourceBundle.getBundle("content.test.Language", locale2);
Enumeration<String> e = labels.getKeys();
while (e.hasMoreElements()) {
String param = e.nextElement();
out.print(param +":\""+ labels.getString(param) +"\"");
if (e.hasMoreElements()) out.println(",");
}
%>
};
Resources._get = _get;
Resources._search = _search;
</script>
What this JSP does is:
Creates object Resources
Using some snippets (sorry Martin :p), and iterating on the list of keys from the resourceBundle, for each key I print a line like "key: value" with out.println().
The resulting object is something like this:
Resources {
abrilAbrText: "Apr"
abrilText: "April"
...
}
To make some extra functionality, I also added 2 functions inside Resources.
_get() returns the text related to the key passed as parameter. If said key doesn't exist, return the text '[ERROR]'.
_search() is a function I added for development purposes. It searches and returns a custom object with every key whose corresponding text contains the text passed as parameter. NOTE: since it uses "e => {}", it won't work on IE or Safari, so it's best to comment it once the development phase has ended.
Once you have this JSP created, to use it you just have to import it to any JSP you want with this:
<%#include file="[relative_path]" %>
Hope it helps! :)
Is it possible to grab a MyBB PHP variable with Javascript? I am an userscript coder, and right now I use:
var uid = $("#panel").find('a').attr('href').replace(/[^0-9]/g, '');
To grab the user id (uid) of the current user. However, if I were to grab the UID from the user with PHP, it would look like this:
<?php echo {$mybb->user['uid']} ?>
Now to the actual question. Is it possible to grab the UID through Javascript, using the $mybb->user['uid']?
My answer is Yes, you can but it has some limits.
Well, if you remember in every headerinclude templates always have these code:
<script type="text/javascript">
<!--
var cookieDomain = "{$mybb->settings['cookiedomain']}";
var cookiePath = "{$mybb->settings['cookiepath']}";
var cookiePrefix = "{$mybb->settings['cookieprefix']}";
var deleteevent_confirm = "{$lang->deleteevent_confirm}";
var removeattach_confirm = "{$lang->removeattach_confirm}";
var loading_text = '{$lang->ajax_loading}';
var saving_changes = '{$lang->saving_changes}';
var use_xmlhttprequest = "{$mybb->settings['use_xmlhttprequest']}";
var my_post_key = "{$mybb->post_code}";
var imagepath = "{$theme['imgdir']}";
// -->
</script>
You can use MyBB's variables in any template with one condition: it's must be defined in the correlative PHP file. (Of course that variable must be inside the brackets { })
For example, the correlative PHP file with headerinclude template is global.php.
That's it. Have fun with MyBB :)
You can add a plugin to your forum. It is called template conditionals. Once you have that installed you can use the Mybb->user variable in all templates. There are many applications of this plugin, but for your code you can do:
<setvar uservar>$mybb->user['uid']</setvar>
var {$tplvars['uservar']} = $("#panel").find('a').attr('href').replace(/[^0-9]/g, '');
The plugin is on the MyBBHacks forum at the link below.
http://mybbhacks.zingaburga.com/showthread.php?tid=464
First, you will not be able to directly access a php server side variable in javascript, but there are several work arounds you could do.
The first one that comes to mind is to put this in your html page somewhere
<script type="text/javascript">
<?php echo "var uid = '". $mybb->user['uid']."';" ?>;
</script>
The downside to this is that this variable is now directly view able and editable in the DOM.
If you are using (or can use) a template you may place a PHP variable in a JavaScript variable defined within that template's content. If you plan to run this JavaScript on every page you must add the variable definition to the script block in the headerinclude template.
<script type="text/javascript">
<!--
var userID = {$mybb->user['uid']};
// -->
</script>
That example script will place the user's uid in the JavaScript variable userID.
Please note that <?php echo $mybb->user['uid']; ?> will not work as MyBB's template system does not allow PHP tags within it. You may instead use {$mybb->user['uid'} as an alternative.
Also, take note that if you are using a plugin and eval'ing the template in a function in your plugin file you will also need to globalise the PHP variable you are going to use.
I have, what I believe, is an extremely simple problem, yet all of my attempts to resolve it have failed.
In a nutshell:
I have a JSP file with a form that invokes a Java Servlet.
The servlet processes the input and returns a variable (attribute) and redirects back to the same jsp.
I want to the jsp to process the returned attribute using JavaScript, NOT a scriptlet.
JSP Code (test.jsp):
<html>
...
<%#page language="java"
import="java.sql.*"
import="java.util.*"
%>
...
<body>
<script type='text/javascript'>
var name = session.getAttribute("test");
alert(name);
</script>
...
</body>
</html>
And the Servlet code:
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
request.getSession().setAttribute("test", "value");
String redirectedPage = "/test.jsp";
RequestDispatcher reqDispatcher = getServletConfig().getServletContext().getRequestDispatcher(redirectedPage);
reqDispatcher.forward(request,response);
}
I believe that the problem stems from my declaration of the session variable:
var name = session.getAttribute("test");
I have also tried:
var name = (String) session.getAttribute("bob");
and:
String name = (String) session.getAttribute("bob");
I can access this attribute from within my form using a scriptlet (<% %>), but that doesn't allow me to modify/process the returned attribute, which I need to do.
Any help is greatly appreciated. If you feel this question has already been asked/addressed (I've searched), please POLITELY let me know.
You can not access the session from javascript, but you can of course create your javascript on the server side.
<script type='text/javascript'>
var name = '<%= session.getAttribute("test") %>';
alert(name);
</script>
If you don't have 100% control of the actual value (and maybe even then) it's is a good idea to escape the string. Otherwise someone might inject values that breaks your page (best case) or enables some XSS to steal user data or hijack user session.
Using Apache commons StringEscapeUtils (JavaDoc) It would look like this
<script type='text/javascript'>
var name = '<%= StringEscapeUtils.EscapeJavaScript((String)session.getAttribute("test")) %>';
alert(name);
</script>
If you are going to use this a lot (or maybe just even once) I'd recommend creating a tag that takes the attribute name and outputs a javascript safe string. Maybe as <MyJsTags:AttributeAsString name="test"/> to avoid script lets in your JSP and it also makes it easier if you want to impose new functionality when accessing the attribute.
How to set the JSTL variable value in java script?
<script>
function function1()
{
var val1 = document.getElementById('userName').value;
<c:set var="user" value=""/> // how do i set val1 here?
}
</script>
How do I set the 'user' variable (JSTL) value from 'val1' (Java script)?
It is not possible because they are executed in different environments (JSP at server side, JavaScript at client side). So they are not executed in the sequence you see in your code.
var val1 = document.getElementById('userName').value;
<c:set var="user" value=""/> // how do i set val1 here?
Here JSTL code is executed at server side and the server sees the JavaScript/Html codes as simple texts. The generated contents from JSTL code (if any) will be rendered in the resulting HTML along with your other JavaScript/HTML codes. Now the browser renders HTML along with executing the Javascript codes. Now remember there is no JSTL code available for the browser.
Now for example,
<script type="text/javascript">
<c:set var="message" value="Hello"/>
var message = '<c:out value="${message}"/>';
</script>
Now for the browser, this content is rendered,
<script type="text/javascript">
var message = 'Hello';
</script>
Hope this helps.
one more approach to use.
first, define the following somewhere on the page:
<div id="valueHolderId">${someValue}</div>
then in JS, just do something similar to
var someValue = $('#valueHolderId').html();
it works great for the cases when all scripts are inside .js files and obviously there is no jstl available
<script ...
function(){
var someJsVar = "<c:out value='${someJstLVarFromBackend}'/>";
}
</script>
This works even if you dont have a hidden/non-hidden input field set somewhere in the jsp.
Just don't. Don't write code with code. Write a JSON object or a var somewhere but for the love of a sensible HTTP divide, don't write JavaScript functions or methods hardcoded with vars/properties provided by JSTL. Generating JSON is cool. It ends there or your UI dev hates you.
Imagine if you had to dig into JavaScript to find something that was setting parameters in the middle of a class that originated on the client-side. It's awful. Pass data back and forth. Handle the data. But don't try to generate actual code.
You have to use the normal string concatenation but you have to make sure the value is a Valid XML string, you will find a good practice to write XML in this source http://oreilly.com/pub/h/2127, or if you like you can use an API in javascript to write XML as helma for example.
This variable can be set using value="${val1}" inside c:set if you have used jquery in your system.
As an answer I say No. You can only get values from jstl to javascript. But u can display the user name using javascript itself.
Best ways are here.
To display user name,
if u have html like
<div id="uName"></div>
You can display user name as follows.
var val1 = document.getElementById('userName').value;
document.getElementById('uName').innerHTML = val1;
To get data from jstl to your javascript :
var userName = '<c:out value="${user}"/>';
here ${user} is the data you get as response(from backend).
Asigning number/array length
var arrayLength = <c:out value="${details.size()}"/>;
Advanced
function advanced(){
var values = new Array();
<c:if test="${empty details.users}">
values.push("No user found");
</c:if>
<c:if test="${!empty details.users}">
<c:forEach var="user" items="${details.users}" varStatus="stat">
values.push("${user.name}");
</c:forEach>
</:c:if>
alert("values[0] "+values[0]);
});
You can save the whole jstl object as a Javascript object by converting the whole object to json. It is possible by Jackson in java.
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonUtil{
public static String toJsonString(Object obj){
ObjectMapper objectMapper = ...; // jackson object mapper
return objectMapper.writeValueAsString(obj);
}
}
/WEB-INF/tags/util-functions.tld:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">
<tlib-version>1.0</tlib-version>
<uri>http://www.your.url/util-functions</uri>
<function>
<name>toJsonString</name>
<function-class>your.package.JsonUtil</function-class>
<function-signature>java.lang.String toJsonString(java.lang.Object)</function-signature>
</function>
</taglib>
web.xml
<jsp-config>
<tablib>
<taglib-uri>http://www.your.url/util-functions</taglib-uri>
<taglib-location>/WEB-INF/tags/util-functions.tld</taglib-location>
</taglib>
</jsp-confi>
mypage.jsp:
<%# taglib prefix="uf" uri="http://www.your.url/util-functions" %>
<script>
var myJavaScriptObject = JSON.parse('${uf:toJsonString(myJstlObject)}');
</script>