Getting a list from Django into Javascript as an array - javascript

I have a python list generated by my views.py in Django, and I would like to pass it to javascript in my HTML template.
I cannot seem to get it into javscript as an array... I need to evaluate if the list/array contains certain numbers, but it is coming over as a string.
I am passing the list to my HTML template like this:
def get_context_data(self, **kwargs):
context = super(dashboardView, self).get_context_data(**kwargs)
mylist = [10,22,33,45]
context['mylist'] = mylist
return context
When I use:
<h1 id = "list"> {{mylist}}</h1>
it shows up on the browser as
it shows up as [10,22,33,45]
Then in my template I am using javascript I have:
var mylist = document.getElementById("list").innerHTML;
for(i = 0; i < mylist.length; i++){
console.log(mylist[i])
};
this returns in the console:
'
[
1
0
,
2
2
........
I want:
10
22
33
45
I have tried to convert to JSON in python, and parse it in javascript, but can't seem to convert this string to an array, or keep getting errors.
Any ideas for the best method here?

If you are absolutely certain your list is safe, (by that I mean it never, ever includes anything entered by a user), it is very simple.
In your view:
context={"my_list": ["item1", "item2"]}
In your template:
{{ my_list|safe }}
Renders as:
['item1', 'item2']
For example:
{{ my_list|safe }}.forEach(item => {
console.log(item)
})
Impressively, if you pass a string with an apostrophe, Django automatically changes the quote types, so
context = {"my_list": ["item1", "it'em2"]}
renders as (note the double-quotes):
['item1', "it'em2"]
so
{{ my_list|safe }}.forEach
still works (tested on Django 3.2.6).
Even this works:
context = {"my_list": ["item1", "it'em\"2"]}
renders as:
['item1', 'it\'em"2']
so
{{ my_list|safe }}.forEach
still works.
However, as I said at the top, if your list might include input from a user, I still wouldn't trust this approach.

In views you can make your object as a JSON object:
import json
mylistraw = [10,22,33,45]
mylist = json.dumps(mylistraw)
context = {''mylistjson': mylist}
Now you can use your object in JavaScript:
var mylist = JSON.parse("{{mylistjson}}")

Django has the json_script template tag that addresses XSS vulnerabilities by escaping the <, >, and & characters.
Django json_script docs here

You can simply use tojson tag to convert python list to js array.
It will be like -
var mylist = {{mylist|tojson}};
for(i = 0; i < mylist.length; i++){
console.log(mylist[i])
};
Try it and let me know if any problem occurs.

In your case, a simple way is to send the list as string ','.join(mylist). And then in your templates, you could simply use split(',') in js.
views
mylist = [10,22,33,45]
context['mylist'] = ','.join([str(i) for i in mylist])
html & js
var mylist = document.getElementById("list").innerHTML;
mylist = mylist.split(',')
for(i = 0; i < mylist.length; i++){
console.log(mylist[i])
};
Or in case your js is in the template as well
var mylist = '{{mylist}}'.split(',');
for(i = 0; i < mylist.length; i++){
console.log(mylist[i])
};

Set the list value in JavaScript and not HTML.
<script>
var mylist = {{mylist}};
for(i = 0; i < mylist.length; i++){
console.log(mylist[i])
};
<\ script>
You need to do this in your HTML template file and not in an external JS file.

Related

How can I dynamically index through datalayer tags in GTM?

I'm using the DuracellTomi datalayer plugin to push cart data from woocommerce to a GTM model to handle some tracking.
The DuracellTomi plugin pushes content to the transactionProducts[] array in the following format:
transactionProducts: Array[1]
0 : Object
category:""
currency:"USD"
id:8
name:"Test"
price:100
quantity:"1"
sku:8
I'd like to loop through this array and unstack it into three separate arrays, pricelist, skulist, and quantitylist. Currently I anticipate doing so as some variation on
//Get Product Information
if(stack = {{transactionProducts}}){
for(i = 0; i < stack.length; i++) {
if(stack.i.sku){
skulisttemp.i = stack.i.sku;
}
if(stack.i.price){
pricelisttemp.i = stack.i.price;
}
if(stack.i.sku){
quantitylisttemp.i = stack.i.quantity;
}
}
{{skulist}} = skulisttemp;
{{pricelist}} = pricelisttemp;
{{quantitylist}} = quantitylisttemp;
}
Obviously this is not going to work because of how the tag referencing is set up, but I'm wondering if anyone has dealt with this and knows what the best way to index through these arrays might be. (For those who don't know, the square bracket array call doesn't work with GTM variables and instead the . format is used instead.)
You would need to create 3 variable type custom javascript function that picks your required value from dataLayer and returns it in an array.
Something like
function(){
var products = {{transactionProducts}};
var skuArray = [];
for(i = 0; i < products.length; i++) {
if(products[i].sku){
skuArray.push(products[i].sku)
}
}
return skuArray
}
hope this helped you :)

How to get the 'Value' using 'Key' from json in Javascript/Jquery

I have the following Json string. I want to get the 'Value' using 'Key', something like
giving 'BtchGotAdjust' returns 'Batch Got Adjusted';
var jsonstring=
[{"Key":"BtchGotAdjust","Value":"Batch Got Adjusted"},{"Key":"UnitToUnit","Value":"Unit To Unit"},]
Wow... Looks kind of tough! Seems like you need to manipulate it a bit. Instead of functions, we can create a new object this way:
var jsonstring =
[{"Key":"BtchGotAdjust","Value":"Batch Got Adjusted"},{"Key":"UnitToUnit","Value":"Unit To Unit"},];
var finalJSON = {};
for (var i in jsonstring)
finalJSON[jsonstring[i]["Key"]] = jsonstring[i]["Value"];
You can use it using:
finalJSON["BtchGotAdjust"]; // Batch Got Adjusted
As you have an array in your variable, you have to loop over the array and compare against the Key-Property of each element, something along the lines of this:
for (var i = 0; i < jsonstring.length; i++) {
if (jsonstring[i].Key === 'BtchGotAdjust') {
console.log(jsonstring[i].Value);
}
}
By the way, I think your variable name jsonstring is a little misleading. It does not contain a string. It contains an array. Still, the above code should give you a hint in the right direction.
Personally I would create a map from the array and then it acts like a dictionary giving you instantaneous access. You also only have to iterate through the array once to get all the data you need:
var objectArray = [{"Key":"BtchGotAdjust","Value":"Batch Got Adjusted"},{"Key":"UnitToUnit","Value":"Unit To Unit"}]
var map = {}
for (var i=0; i < objectArray.length; i++){
map[objectArray[i].Key] = objectArray[i]
}
console.log(map);
alert(map["BtchGotAdjust"].Value)
alert(map["UnitToUnit"].Value)
See js fiddle here: http://jsfiddle.net/t2vrn1pq/1/

Object to array - quick conversion

I have a Json structure of this kind:
this is generate from the backend (I'm using Firebase) and put in a variable :
var newJson = {}
I'm using AngularJS and ng-repeat though this variable to show the results - and it works. I d like to order the JSON by votes property and I have tried use the angularJS
| orderBy: 'vote' "
But that doesn't work cos I'm "ng-repeating" though a JSON and not array.
I have tried different solutions showed at https://github.com/angular/angular.js/issues/1286
but I couldn't make work any of them.
So I thought to go for the easy road and converting my JSON to array.
I ve tried :
var arreyM = [];
for (var i = 0; i < $scope.newJson.length; i++) {
arreyM.push(name: $scope.newJson[i].name, pic: $scope.newJson[i].pic, vote:$scope.newJson[i].vote);
}
but it gave me error - I guess the syntax is wrong.
try this
var arreyM = [];
for (var i = 0; i < $scope.newJson.length; i++) {
arreyM[i]['name']= $scope.newJson[i].name;
arreyM[i]['pic']= $scope.newJson[i].pic
arreyM[i]['pic'] = $scope.newJson[i].vote;
}
Hope it will help

Python HTML getElementsByClassName alike manipulate on file content

I have saved the source code of a page to a file using Sikuli. I need a "roundup" on a batch of matrix style placed elements. But I don't want to calculate dimensions between them. I want URLs to type in location bar. So I wrote from scratch with a help of MZDN JavaScript implementation of such a "simple" operation. I don't want to use lxml. I want real native libraries - I mean I need "portable" script.
So I've googled a while and decided to ask a question at Stack OverFlow.
I don't want to use
split('<a href=')
magic.
I would like to do this in Python(in the most pythonic way):
var array = document.getElementsByClassName('another')
var j = array.length
for (i=0;i<j;i++) {
element = array[i];
url = element.getElementsByTagName('a')[0].href;
console.log(url);
}
var array = document.getElementsByClassName('else')
var j = array.length
for (i=0;i<j;i++) {
element = array[i];
url = element.getElementsByTagName('a')[0].href;
console.log(url);
}
Managed to do it with split. Python is for kids.
def read_file(filename):
fd = open(filename, 'r')
data = fd.read()
fd.close()
return data
def href(line):
url = line.split('a href=')[1].split('>')[0].strip().replace('"', '').replace("'", '')
return url
html = read_file('source.htm').split('\n')
for line in html:
if 'one' in line:
print href(line)
elif 'another' in line:
print href(line)
elif 'else' in line:
print href(line)

Using c# code in javascript

I am trying to use C# in javascript like we are using it in MVC Razor View using # sign,
like suppose an array name list is passed to the View so we can access it in View like:
View
Length of array : <input type="text" value="#Model.list.Length" />
Or we can iterate list array also like:
#for(int i=0; i< Model.list.Length; i++)
{
console.log(Model.list[i]);
}
But my question is how we can iterate or use this array in the javascript code , something similar to :
JS
for(var i=0; i<#Model.list.Length; i++)
{
$("body").append("<h1></h1>").html(#Model.list[i]);
}
Thanks !
As i posted in my comment, this is a bit tricky. However, you can try to construct a javascript object with your c#.
Something like this (i don't know how this works exactly...):
var array = [
#for(var i = 0; i < Model.list.Length-1; i++){ #Model.list[i] , }
#Model.list[length]
]
which should result in:
var array = [
val1,
val2,
val3,
valn
]
Now you have an js var array, you can work with in your entire document.
You can't do it exactly that way. What you can do is use the C# to generate the javascript code for each line like this:
//...javascript code...
#for(var i = 0; i < Model.list.Length; i++)
{
$("body").append("<h1></h1>").html('#(Model.list[i])');
}
//...more javascript code...
This should output like this:
//...javascript code...
$("body").append("<h1></h1>").html(listitem0);
$("body").append("<h1></h1>").html(listitem1);
$("body").append("<h1></h1>").html(listitem2);
//etc.
//...more javascript code...

Categories

Resources