Having spent a week trying to get a java ArrayList to 'appear'in javascript (in the same jsp) I am at the point of giving up as
none of the supposed 'examples' in various forums works.
As a last resort I attempted this with JSON, but that doesn't work either.
If this is an impossibility then can someone confirm that?
There is a SQL select followed by a c:set (in JSTL) followed by a java ArrayList (in a java scriplet in the same jsp) inside a c:forEach loop.
This is working properly and the output is 1 6 3 2 1 7 etc
There is also a StringBuffer which adds commas,
this is also working properly and the output is 1,6,3,2,7 etc.
I now want that same array, in the same format, to appear in javascript
(in the same jsp) so I can use it for dynamic arrays in chart.js.
Hence my 'final' attempt' to use JSON.
It doesn't matter whether the JSON is after the ArrayList or after the StringBuffer as long as I can get the array into javascript.
However the JSON code produces what appears to be each element of the array in its own square brackets (jsonQuantities = [1] jsonQuantities=[6] etc
<c:set var="quantity" value="${row.Quantity}" />
<c:set var="zone" value="${row.zone}" />
<%
//produce array
ArrayList quantities= new ArrayList();
quantities.add(pageContext.getAttribute("quantity"));
//convert to JSON
Gson gson = new Gson();
String jsonQuantities = gson.toJson(quantities);
out.println("jsonQuantities = " + jsonQuantities);
//add commas
StringBuffer thesequantities = new StringBuffer();
for(int i=0; i<quantities.size(); i++)
{
thesequantities.append(quantities.get(i));
thesequantities.append(",");
}
out.println(thesequantities.toString());
%>
</c:forEach>
Then I attempt to get the array into javascript - the JSON.parse line does nothing other than prevent any JavaScript below it from executing.
I have tried various forEach loops and so called 'conversions' to output the array
but nothing works.
<script type="text/javascript">
var myobject = JSON.parse("jsonQuantities");
document.write("the quantities are" +myobject.count);
All the examples using c:forEach (i.e. below), getParameter, getAttribute etc do not work.
var jsArray = [
<c:forEach var="item" items="${jsonQuantities}">
<c:out value="${item}"/>,
</c:forEach>
];
Does anybody have actual working code / experience of this (without using separate php, jsp's etc)?
All I need is the java ArrayList (1 6 3 2 1 7 etc) or StringBuffer (1,6,3,2,7 etc) contents 'transferred' to javascript and then output (so I can see all the elements
irrespective of what they are named or in which format they are in).
Thanks, Ralph
Related
i have a Java ArrayList and i want to send it to the javascript for another purpose.
this is my Java ArrayList
List<String> list = new ArrayList<String>();
list.add("xxx");
list.add("yyy");
....
model.addAttribute("theList", list);
and how to send the ArrayList into javascript Array?
i'm expecting this in my javascript code
<script th:inline="javascript">
var Array = ["xxx","yyy","xxx"];
</script>
i'm truly sorry for asking this type of question again, i know there's already answered questions and duplictae questions about this case, but i don't really understand the answer. maybe some JSON things or other ways.
please show me how to write the code both in java code and javascript code.
Thanks.
As mentioned in the comments, you can use a library to serialize the object as a json string. In other words, you can convert each list element to a json object node and put all the json object nodes into an array.
What a serializer does
It takes a look at your object(s) and creates a json representation out of it/them (serializes). The opposite of a serializer is a deserializer, to convert a json string into Java objects.
Why use a library
While you could do it by hand (see below), a library such as Gson as mentioned in the comments, or jackson in the open source community has been tested on a large number of test cases and will in all likelihood be robust enough for whatever your use case is.
Example with jackson
See here.
Example "do it yourself"
Your case is very simple since your list elements are strings.
// create a string builder to build the json
StringBuilder sb = new StringBuilder();
// loop over each string in the list
for (String s : list) {
// add an initial delimiter, which will be
// removed at the end
sb.append(",");
// add a beginning quote to each term
sb.append("\"");
// add the string
sb.append(s);
// close the quote
sb.append("\"");
}
if (sb.length() > 0) {
// if there was at least one element
// in the list, remove the initial comma
sb.deleteCharAt(0);
}
// add a left square bracket
sb.insert(0, "[");
// add a right square bracket
sb.append("]");
// your string, for example
// ["one","two","three"]
String json = sb.toString();
Going back to "why use a library", the above code doesn't account for a lot of possibilities, the most obvious of which, if one of the strings in the list contains a " character it will mess everything up. Note that there are many ways to handle the above.
I hope that helps.
Scriptlet tag allows to write Java code into JSP file.
Syntax
<% java code %>
Here <%%> tags are scriplets tag and within it, we can place java code.
`<% List<String> strList = new ArrayList<String>();
strList.add("xxx");
strList.add("yyy");
strList.add("zzz");%>`
var jsArray = [<% for (int i = 0; i < strList.size(); i++) { %>"<%= strList.get(i) %>"<%= i + 1 < strList.size() ? ",":"" %><% } %>];
The output will be
var jsArray = ["xxx","yyy","zzz"];
The VB multidimensional array (arrHotelsProdCols) is created in classic .ASP vb thus:
strSQLHotelsProdCols = "SELECT * FROM qryHotelProdCols"
rsHotelsProdCols.Open strSQLHotelsProdCols, ConString
arrHotelsProdCols = rsHotelsProdCols.GetRows
The VB array works fine, over 600 rows, 4 cols. I can loop through it and display it in a table in the source .asp file html, etc.
I want to add a function to my existing validateform.js ‘included’ file that will fire onchange of one dropdown in an existing form in the same .asp file as the VB multidimensional array, search for a unique value and populate other fields in the form with other values on the same row in the multidimensional array – that part is not so difficult for me and is another question if I get stuck when I get there.
1) How do I convert and pass my VB multidimensional array to a javascript array for use in my validateform.js file?
Explanations
In fact, as your question is stating, a VB Array CAN BE multidimensional.
But the JScript Arrays CANNOT BE multidimensional : They are only one-dimension.
(see. https://wiki.mcneel.com/developer/scriptsamples/arrays)
Solution
So, the solution is to list all the elements of your JScript one-dimension array, and try to detect when you have reached a new "Row". How can we know that ? We can simply know that when the RowNumber Modulus NumberOfColumns is Zero, then it IS in fact a new row.
This may seem a bit "hacky", but it is 100% fully functional, even in a production environment :-)
Here is the source code of the VBScript part, and of the JScript part :
The VBScript Part
<%
'Declare SQL Statement
Dim strSQLHotelsProdCols
strSQLHotelsProdCols = "SELECT * FROM qryHotelProdCols"
'Execute SQL Statement
rsHotelsProdCols.Open strSQLHotelsProdCols, ConString
'Populate Two-Dimensional VB Array
arrHotelsProdCols = rsHotelsProdCols.GetRows
%>
The JScript Part
<script runat="server" language="JavaScript">
//Convert a VBScript Two-Dimensional array => To => JScript One-Dimensional array
//Yes : Infortunately, JScript can only manage 1-Dimension Arrays !
var tmp_VBArray = new VBArray(arrHotelsProdCols);
var tmp_VBArrayInJs = (tmp_VBArray).toArray();
//As all the "VB columns" (2-dimension array) have been converted into "JS rows" (1-dimension array),
//We will manually detect when a new Row has started using the modulus (%) operator :-)
//For each row in the One-Dimension JScript array
for (var iRow = 0; iRow < tmp_VBArrayInJs.length; iRow++) {
//Test if a new row has started
var testNewRow = (iRow + 1) % (tmp_VBArray.ubound(1) + 1);
//If a new row is detected
if (testNewRow == true){
response.write('<br>=> NEW ROW STARTED<br>');
}
//Write the fields
response.write('<strong>'+iRow+'. </strong>');
response.write(tmp_VBArrayInJs[iRow] + '<br>');
}
</script>
From Help.
But I'd just give jscript the recordset.
VBArray Object (JScript 5.6)
Provides access to Visual Basic safe arrays.
varName = new VBArray(safeArray)
Arguments
varName
Required. The variable name to which the VBArray is assigned.
safeArray
Required. A VBArray value.
Remarks
VBArrays are read-only, and cannot be created directly. The safeArray argument must have obtained a VBArray value before being passed to the VBArray constructor. This can only be done by retrieving the value from an existing ActiveX or other object.
VBArrays can have multiple dimensions. The indices of each dimension can be different. The dimensions method retrieves the number of dimensions in the array; the lbound and ubound methods retrieve the range of indices used by each dimension.
Example
The following example consists of three parts. The first part is VBScript code to create a Visual Basic safe array. The second part is JScript code that converts the Visual Basic safe array to a JScript array. Both of these parts go into the section of an HTML page. The third part is the JScript code that goes in the section to run the other two parts.
<HEAD>
<SCRIPT LANGUAGE="VBScript">
<!--
Function CreateVBArray()
Dim i, j, k
Dim a(2, 2)
k = 1
For i = 0 To 2
For j = 0 To 2
a(j, i) = k
document.writeln(k)
k = k + 1
Next
document.writeln("vbCRLF")
Next
CreateVBArray = a
End Function
-->
</SCRIPT>
<SCRIPT LANGUAGE="JScript">
<!--
function VBArrayTest(vbarray){
var a = new VBArray(vbarray);
var b = a.toArray();
var i;
for (i = 0; i < 9; i++)
{
document.writeln(b[i]);
}
}
-->
</SCRIPT>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JScript">
<!--
VBArrayTest(CreateVBArray());
-->
</SCRIPT>
</BODY>
Properties
The VBArray object has no properties.
Methods
dimensions Method | getItem Method | lbound Method | toArray Method | ubound Method
Requirements
Version 3
I have a code that looks like this:
In AnalyzeUserClient.jsp:
<c:set var="arrayList"><%= (ArrayList<String>)request.getSession().getAttribute("arrayList") %></c:set>
var sessionId = [];
<c:forEach items=${arrayList} var="id">
sessionId.push("${id}"); // add them one at a time, assuming string values
</c:forEach>
However,this line:
sessionId.push("${id}");
does not seem to be passing the values into the array "sessionId" (I viewed the source code on browser).So the question is,what can I do to pass the values into the array?
EDIT:I just realised that there are some problems as JSTL is server-side and JavaScript is client-side.So is there a workaround on it?
Don't mix EL and scriptlets. In fact, forget about scriptlets completely:
var sessionId = [];
<c:forEach items="${sessionScope.arrayList}" var="id">
sessionId.push("${id}");
</c:forEach>
Note though that this will generate invalid JavaScript if one of the IDs happens to contain a double quote. So you'd better JavaScript-escape the IDs before, in your controller. And I would suggest a completely different approach: serialize the list of IDs to a JSON string in your controller, and store this JSON string in request attribute. The JSP page will just need
var sessionId = ${jsonEncodedSessionIds};
which will translate to the following generated code:
var sessionId = ["id1", "id2"];
I know there a couple of threads similar to this one but they dont actually answer the above question.
Firts question: is it true that only primitives can be passed? (String, boolean,...)
Second question: if it is so. I have an array of String in my activiy and i need it to fill a html table in my WebView and apparently i need to use Javascript interface to do so. So the question is: How can i do that? Do I need to create a string in my activity, pass it to JS and once there recreate the array?
You could use JSON as format for your data. A simple way would be to use a lib like GSON http://code.google.com/p/google-gson/ which makes it easy to convert your ArrayList with own object-types to Strings.
Send that to your WebView via the Javascript-interface and use JSON.parse(Stringname) in JS to recreate your Array.
Best wishes,
Tim
Your option is to expose the method using strings and then you can use the JSONObject or JSONArray to parse the string and use it accordingly.
Here is what I did.
#JavascriptInterface
public void passJSON(String array, String jsonObj) throws JSONException
{
JSONArray myArray = new JSONArray(array);
JSONObject myObj = new JSONObject(jsonObj);
...
}
where array is '["string1","string2"]' and jsonObj is '{attr:1, attr2:"myName"}'
"Do I need to create a string in my activity, pass it to JS and once there recreate the array?"
That's the way i resolved it in my case ; i appended a special character to each item in the list while building up the string and later split it up in JS.
var strings = get.list(); // long string from activity.
var item1 = strings.split("=")[0];
var item2 = strings.split("=")[1];
....
Or you could go for a library
I was wondering if I could pass a IEnumerable Collection into a Javascript method on the page load. So something like this...
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MyAppMVC.Models.ViewModels.News.NewsIndexViewData>" %>
<div id="container">
<%= String.Format("<script type='text/javascript'>testMethod({0})</script>", Model.NewsList) %>
</div>
I realize JS is client side, just didn't know if there was any way possible to do that?
Thanks!
No, you cannot. For several reasons.
1) There is no IEnumerable in JavaScript, as you use it in .NET. There is something similar, but it is implemented completely differently. In .NET, IEnumerable just means the class provides a method, GetEnumerator(), which returns an IEnumerator (which itself only contains Current, MoveNExt, and Reset methods). In JavaScript, when you do a for iteration on an item, you are iterating over the names of its properties.
var myObj = { 'a' = 1, 'b' = 2 };
for (var name in myObj) { alert(name); } // will alert 'a', and 'b'
Even when working with JavaScript arrays, the above loop returns the index of the array element, not the actual member at that index.
2) By doing a String.Format() on your list, you wouldn't have been passing the list as an object to your JavaScript but just the ToString() result of your list. Which probably just returns "System.Collections.Generic.List`1[System.String]"
3) Unless your developing environment explicitly allows it, you can assume that passing arguments from one language into another is not going to work. Much like you can't write JavaScript inside your .NET code, you can't write .NET code in your JavaScript. These languages have different feature sets, different syntax, and are executed with completely different mechanisms - .NET is compiled, and JavaScript (generally, speaking) is interpreted (Compiled vs. Interpreted languages).
What you have to do is transform your data into a format that can be used by JavaScript. Most likely this means converting it into something called JSON. You didn't provide a lot of details as to what exactly Model.NewList is, or what your testMethod() expects as an argument. But for the sake of an example lets assume NewList is a list of strings. In that case, your JSON would look something like this:
{ 'NewList' : ['string1', 'string2', 'string3'] }
The easiest way to convert your .NET data into JSON is to use built-in libraries, such as JavaScriptSerializer:
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string json = serializer.Serialize(Mdoel.NewList);
You can register the javascript in the code behind in the Page_Load with the following code (Note I am assuming that Model.NewsList is a string enumeration or array):
StringBuilder sb = new StringBuilder();
bool isFirst = true;
//build a comma seperated list.
foreach (string s in Model.NewsList)
{
if (isFirst)
isFirst = false;
else
sb.Append(", ");
sb.Append("'").Append(s.Replace("'", "''")).Append("'");
}
//create the javascript array
string javascript = String.Format(#"var news = [{0}];", sb);
//put the array in the generated page.
Page.ClientScript.RegisterClientScriptBlock(GetType(), "newsList", javascript);
This will put the javascript on the page accessible from other javascript functions.