Attempting to use .get method on java variable in javascript - javascript

I'm trying to create a webpage (using the play framework) which displays the user's name, date of birth etc. Where I am getting stuck is attempting to display a list of unknown size in an html page. I currently have:
#(currentUser : Profile)
#main("Profile") {
<div>
<h1><b>#currentUser.getFirstName() #currentUser.getLastName()</b></h1>
<p>#currentUser.getDateofBirth</p>
<b>Nationalities</b>
<ul><p id="natInput"></p></ul>
<script>
for (var i = 0; i < "#currentUser.getNationalities().size()"; i++) {
document.getElementById("natInput").innerHTML += "<li>" + "#currentUser.getNationalities().get(i)" + "</li>";
}
</script>
</div>
}
Profile is a basic java class which only contains getters and setters, and .getNationalities returns a List.
#Main is another html file which stores the base design of the website, not really relevant to this.
As you can see, I'm trying to use the .get method to loop through the list of nationalities for the user, but unfortunately the "i" variable used in the get is not recognised, as it is a javascript variable in html.
Every other part of this code appears to work as expected, and the .get works when the "i" is replaced with an integer, such as 0 or 1.
Any ideas how I could get each individual element of this list? Any help would be greatly appreciated

The problem is that you are messing up different step of the page generation.
First of all we should clear out the processing steps from a render command in a Play controller to a fully rendered page in the browser.
Twirl is a template engine that allow you to generate HTML pages with Scala.
This step is performed on server side, before the HTML page is sent to the browser.
In this step the Javascript code is not being considered.
So the first step after the render command, the twirl template is picked and rendered, evaluating each Twirl/Scala instructions. This will generate an HTML file with no more Scala code.
This generated page is sent to the browser. Then the page is loaded into the browser and the Javascript code is evaluated as any other HTML page with JS.
This would explain why you are not able to render the page the way you are doing.
A proper way, if your page is static, is to use only twirl instructions to iterate over the array Twirl Template - Iterating
You should be able to rewrite your list generation like the following if getNationalities() method returns a Scala List
<ul>
#for(nationality <- currentUser.getNationalities()) {
<li>#nationality</li>
}
</ul>

Related

How to transfer array values in JS to html before the file switches using Ajax

This is the HTML code in file 1, which is calling the function. It is linked to javascript
<form id='next' action='file2.html'>
<button id="nextTwo" onclick="nextTwo()">next2</button>
</form>
This is the JS code that receives the function.
function nextTwo(){
document.getElementById('question').innerHTML=question
}
It is searching for the id before the file changes to where the id is.
Every time I press the button that calls the function it gives me:
"TypeError: Cannot set properties of null (setting 'innerHTML')"
This is because it is searching for the id of "question" in file 1, but the id is in file 2. It tries to find the id in file 1, then it switches to file 2, where the id of "question" is.
How do I make it so that is switches to file 2 first, then searches for the id.
Maybe an if statement with a condition, if the file is switched, although I don't know the how to write that.
Thanks for your help.
This is my Js code, how do I place the arrays value into the file 2 using ajax?
let ants;
let question;
let squestion;
function check() //CHECK
{
switch(1){ //different header number is fine but do '' BUT input box will still be there
case 0:
ants = ['calculations']
question=["Element Symbol that has the atomic number of... ","atomic mass of (round to nearest whole number)..."]
squestion=["1. 50","2. 2","3. 20","4. K"]
case 1:
ants = ["0 (all atoms have a charge of 0)","11","11","4","9","Be","8","8","8"]
question=["Sodium has 11 protons and an mass of 23. What is the...","An atom has an atomic# of 4 and 5 neutrons What is the...", "Oxygen has 8 electrons and a mass of 16"]
squestion=["charge","atomic#","#of electrons", "#of protons","Mass","element symbol", "#of protons", "atomic#", "#of neutrons"]
// ants = ["Sn ","He ","Ca ","39 ", "32 ","Sn ","He ","Ca",]
// question=["Element Symbol that has the atomic number of... ","atomic mass of (round to nearest whole number)..."]
// squestion=["1. 50","2. 2","3. 20","4. K"]
break;
case 2:
ants = ["Carbon", "Chlorine", "Bromine",'Br',"Li","Sc","2","8","8" ]
question=["Carbon", "Chlorine", "Bromine", "Helium",'Br',"Li","Sc" ]
squestion=[]
}
There is a better way to go about this.
By design, forms do not communicate two-way. They take the data entered by the user and carry it over to the processing file (defined by the action= parameter on the form tag). The user is navigated away from the first webpage, and the view changes to that processing file - and it isn't supposed to go back to the first file again. Forms are very basic, primitive constructs.
This is why forms have been almost entirely replaced by AJAX. AJAX is a very simple JavaScript construct (made even simpler via jQuery - TANGENT: although jQuery is no longer recommended because modern JavaScript has made the process much easier - but the jQuery $.ajax() method still works fine and there is tons of info about how to use it).
AJAX allows you to send data from a web page to a back-end (server-side) file that receives any data you send it (optional), does something (optional), and returns new data (optional). The page the user is on need not change, blink or flash. New data received from the server-side file can be received and actively used before returning control to the user... So this sounds like exactly what you need it to do.
The back-end (AJAX) processing file is written in a server-side language (PHP, NodeJS, ASP.Net, Python, etc - PHP is a very popular one for AJAX), but you did not specify which one you wish to use, which is likely why no one responded to your question sooner.
Here are some references that might help. I chose jQuery examples because the AJAX code block $.ajax( //code goes here ).done() is very simple. To do AJAX in pure JavaScript, look for information regarding the Fetch API (newest), and XmlHTTPRequest (older).
Simple jQuery example
Ajax explained with jQuery
Another simple example with explanation
Here is a pure javascript video tutorial (5 mins)
After reviewing the examples, you can construct a basic AJAX test on your side and, if you have any trouble with it, ask another question specifying which language you are trying to do this with, and showing your code so far.

Iterating over a list of django created objects in Javascript, is it possible? Template language in Javascript

My site can't run a successful for-loop created in django for a list model that I have sent to a page. I was going based off of Derek's answer in this stackoverflow question and some other things I found. But right now... It seems that my browser (Google Chrome if that helps) can't seem to render the {% for %} loops that I attempt to run in javascript on my html file.
I have two python/django created two list models, booklist_greek and booklist_latin that are sent to my textlist.html file. These lists contain sorted 2-tuples, each tuple having the title of a book as the first element and the type of the book as a second element. Using template-language in html to run a for loop works just fine at two parts in my html file.
There's a point in my code where I would like to filter booklist_greek and booklist_latin based on the booktype of each book, and use that to populate a <select> element. This filtering and populating needs to happen when a user clicks buttons. So I assumed javascript would be necessary... But I also needed template language to somehow filter the lists.
I approached it like so. But this doesn't work.
var latinBooks = $("#latinTextsDropDown");
$("#latinTextsDropDown").children().remove();
{% for each in booklist_latin %};
var bookTitle = {{ each.0 }};
var bookType = {{ each.1 }};
if (bookType == filteringType) {
var opt = document.createElement("option");
opt.value = bookTitle;
opt.name = bookType;
...
$("#latinTextsDropDown").appendChild(opt);
}
{% endfor %};
I even tried reducing the contents of the {% for %} loop to just be the following: console.log({{ each.0 }}) but that failed as well. However if I make the for-loop contain no template-language, so for instance if it only had console.log("hello world!"); then that actually works. Any template language calls to the objects that are being iterated over, and interestingly enough... No java code within my <script> tag runs at all.
So now I need an alternative, or I need to figure out what I'm doing wrong. I understand that what I was doing was pretty odd from the start. But is there another way to iterate over objects within booklist_latin and booklist_greek? And to check what is actually in each tuple with each iteration?
You can only use python in html. This is because it gets rendered on the server before it is sent to the client (chrome). In your case js is used for handling logic on the client side (chrome). Knowing this you have two options:
Use the python in the html to loop through your books. You create a filter which calls the action that rendered the page but you pass a parameter that specifies what you want to filter. Python will do a page a page refresh because python has to re-render the html.
Your javascript either does a GET request to your server asking for the books or you send a json encoded array of the books when your page loads. You use js to render the books into the html and your filter calls a js function which will filter the js books array. If you install something like jquery it will help a lot.
Option 1 is probably easier for you and there's most likely documentation in django showing you how to do this. Option 2 is more user friendly.

Attempting to use a global array inside of a JS file shared between 2 HTML files and failing

So I have one HTML page which consists of a bunch of form elements for the user to fill out. I push all the selections that the user makes into one global variable, allTheData[] inside my only Javascript file.
Then I have a 2nd HTML page which loads in after a user clicks a button. This HTML page is supposed to take some of the data inside the allTheData array and display it. I am calling the function to display allTheData by using:
window.onload = function () {
if (window.location.href.indexOf('Two') > -1) {
carousel();
}
}
function carousel() {
console.log("oh");
alert(allTheData.toString());
}
However, I am finding that nothing gets displayed in my 2nd HTML page and the allTheData array appears to be empty despite it getting it filled out previously in the 1st HTML page. I am pretty confident that I am correctly pushing data into the allTheData array because when I use alert(allTheData.toString()) while i'm still inside my 1st HTML page, all the data gets displayed.
I think there's something happening during my transition from the 1st to 2nd HTML page that causes the allTheData array to empty or something but I am not sure what it is. Please help a newbie out!
Web Storage: This sounds like a job for the window.sessionStorage object, which along with its cousin window.localStorage allows data-as-strings to be saved in the users browser for use across pages on the same domain.
However, keep in mind that they are both Cookie-like features and therefore their effectiveness depends on the user's Cookie preference for each domain.
A simple condition will determine if the web storage option is available, like so...
if (window.sessionStorage) {
// continue with app ...
} else {
// inform user about web storage
// and ask them to accept Cookies
// before reloading the page (or whatever)
}
Saving to and retrieving from web storage requires conversion to-and-from String data types, usually via JSON methods like so...
// save to...
var array = ['item0', 'item1', 2, 3, 'IV'];
sessionStorage.myApp = JSON.stringify(array);
// retrieve from...
var array = JSON.parse(sessionStorage.myApp);
There are more specific methods available than these. Further details and compatibility tables etc in Using the Web Storage API # MDN.
Hope that helps. :)

Load another HTML page to create an JavaScript array using .get and .each

So I've banged my head on this all day. I'm updating the code.
I'm trying to pull an array based off of an HTML page (we'll call this switcher1.html) where there is a list.
Based on this array, the javascript will randomly load one item of the array onto the page where the javascript is called (we'll call this index.html).
//
// Random Profile
//
function randomProfile() {
var profilePages = [];
$.get( "/js/switcher1.html #featured-faculty", function() {
$("ul li").each(function( index ) {
profilePages.push($(this).text())
});
});
var randomPage = Math.floor(Math.random() * profilePages.length);
$('#featured-profile').load(profilePages[randomPage]);
}
// Run these functions as soon as this script is loaded,
// instead of waiting for the DOM to finish loading
randomProfile();
Hopefully you can see that the goal is to pull in a list from another source so I won't have to type it in to the JavaScript doc manually. My array is turning up blank no matter what I try.
FYI - I can use JQuery but not other code libraries. Also, I'm doing it this way due to a (slightly annoying & convoluted) CMS. The CMS can output an HTML list, so this is the best solution I was able to come up with.
Thanks in advance for your help!

AngularJS and embedded framework html

I'm developing a user preferences page and I've decided to use AngularJS to control the state of the data.
What I would like to achieve is a page that shows the current user's settings and allows a user to edit them, cancel their changes, or save & submit changes if they so desire. I've binded my labels and my input controls to the model so that when a user modifies their email address, it is reflected across correctly.
I'm basing my work off this example #3 by the way: http://code.angularjs.org/1.0.0rc12/docs-1.0.0rc12/guide/forms
My question is related to the default values for the page. Since the model is defined as an object in Javascript. In the link above, default values can be set over here in $scope.master= {}; which works fine except that I'm using a framework to generate a static page and not retrieving an json object from my server. My pages are all written in embedded scala, so I access the values serverside. What is the best way to take the info retrieved serverside and turn into an object client side javascript can access?
You have a few choices. The way I would do it would be to push the initial state (through a WebSocket or something) to Angular as JSON, or have Angular pull it from the server through an HTTP call.
You could also perhaps render the page with ng-init tags to set the initial state, but this way seems weird to me.
<div ng-controller="FormController" ng-init="formData = {}">
<form>
<input ng-model="formData.input1" ng-init="formData.input1 = 'initialValue'>
</form>
</div>
I am using ASP.NET and Dapper-Dot-Net. I use the following techniques to get my data on to the page and then into Angular scope. It should be pretty transferable to your environment.
Define a DataTransferObject class in the page on the server side and a public string called DtoJson to hold the serialized version of your class instance.
private class DataTransferObject{
public User User;
public List<Project> Projects
}
public string DtoJson;
var dto=new DataTransferObject();
var userName="however you get a username";
dto.User=User.Get(userName); // I already have a User class
var sql="select * from projects where user_name=:UserName";
var p=new DynamicParameters();
p.Add(":UserId", dto.User.ID);
dto.Projects=Project.Query<Project>(sql, p); // returns a list of Project
// I use json.net to convert the Dto to json and expose it as a public variable
var DtoJson=Json.Convert(dto); // approximate syntax but you get the idea
On the client side I put a script tag at the head of the page and inject the DtoJson into it to get it into the global scope
<script>var dto=<%=DtoJson%>;</script>
At the bottom of my page I have a script src="pageName.js" which is my Angular controller file. Inside the controller I say
$scope.dto=dto;
console.log($scope.dto);
Now the json that was created on the server side is in my controller's scope and I can data bind to {{dto.User.FIRST_NAME}} and {{dto.Projects[0].ID}} ng-repeat="for p in dto.Projects" etc
I hope that that makes sense.
Peter

Categories

Resources