I want to implement below using javascript so row click it will get index and display object of this index.
in django template this is working.
<div>{{ project.0.customer_name}}</div>
<div>{{ project.1.customer_name}}</div>
but the below javascript are not working even I get the correct ID.
var cell = row.getElementsByTagName("td")[0];
var id= parseInt(cell.innerHTML);
// not working
document.getElementById('lblname').innerHTML = '{{ project.id.customer_name}}';
// this is also working but what I want is dynamic base on row click
document.getElementById('lblname').innerHTML = '{{ project.1.customer_name}}';
display django object using index in javascript.
You have to understand what is happening with your code:
Templates like this are processed on the server:
'{{ project.id.customer_name}}'
I believe you do not have project.id on your server side, so you get None in the above line, and the moustache tag becomes smth like an empty string, and actual JavaScript code is like this:
document.getElementById('lblname').innerHTML = '';
It is only now that JS code is executed, and you can imagine what it will do.
What you want is processing moustache tags after the id variable has been set in JS, which is not how stuff works (at least, if you don't have some crazy tool chain).
One way of achieving what you want is to provide the whole project object (or array) to JavaScript by doing the following:
<script>
const project = {{ project|safe }};
</script>
A complete Django template could look like this (I used <span>s instead of table cells:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>django test</title>
</head>
<body>
{% block content %}
{% for item in project %}
<span data-id="{{ forloop.counter }}">{{ forloop.counter }}</span>
{% endfor %}
<div id="output" style="display: flex; flex-direction: column-reverse;">
</div>
<script>
const project = {{ project|safe }};
const spans = document.getElementsByTagName('span');
const output = document.getElementById('output');
const onSpanClick = (event) => {
const id = parseInt(event.target.getAttribute('data-id'), 10) - 1; // forloop.counter is 1-based, JS arrays are 0-based
const div = document.createElement('div');
div.innerHTML = project[id].customer_name;
output.appendChild(div);
}
Array.from(spans).forEach(span => {
span.addEventListener('click', onSpanClick);
})
</script>
{% endblock %}
</body>
</html>
Another way is the AJAX way: you create an API endpoint on your server side, so that an URL like example.com/api/customer_name/?id=999 responds to you with the name of customer id=999 when you click on some element and trigger an XMLHttpRequest with param id=999.
Related
Like we can access a variable in the JS part like "{{vaiable_name}}". How can we update the value of variable_name inside the javascript?
Let's say code will look like this,
{% if variable_name %}
<p> Condition is true </p>
{% endif %}
One way is to inject a small Javascript through the Django template engine, with {{variable}} substitution.
My own base.html contains
<script type="text/javascript"> $(document).ready( function() {
{% block onready_js %}{% endblock onready_js %}
});
</script>
and then in any template extending base.html where I want to pass variable values, I can simply code
{% block onready_js %}
/* some JS with Django substitutions */
var foo = "{{foo}}";
...
{% endblock %}
The one thing you have to remember is that your JS must not contain consecutive open- or close-braces without a space between them!
(If the block is not defined, then the base.html defines a null function to be executed when the document is ready)
you can add a span tag with an id and then target the id within javascript
<span id='django_variable_id'>{{variable_name}}</span>
<script>
function update_django_variable(new_var){
/* get the span element */
var span = document.getElementById('django_variable_id');
/* set new var here */
span.innerText = new_var;
}
</script>
or will also work as long as there are no other variables with this name
<span id='var_{{variable_name}}'>{{variable_name}}</span>
<script>
function update_django_variable(new_var){
/* get the span element */
var span = document.getElementById('var_{{variable_name}}');
/* set new var here */
span.innerText = new_var;
}
</script>
First of all, I will like to say this is my first question here! (pardon me if this is redundant or duplicated)
I am having some problems with calling JS scripts from Django template:
{% for suggestion in suggestions %}
<img class="catalogue-poster" src="{{ suggestion.poster }}" alt="Portada" onclick="
document.getElementById('{{form.title.auto_id}}').value = '{{suggestion.title}}'
document.getElementById('{{form.year.auto_id}}').value = '{{suggestion.year}}'
document.getElementById('{{form.director.auto_id}}').value = '{{suggestion.director}}'
document.getElementById('{{form.rating.auto_id}}').value = '{{suggestion.rating}}'
document.getElementById('{{form.poster.auto_id}}').value = '{{suggestion.poster}}'
document.getElementById('{{form.trailer.auto_id}}').value = '{{suggestion.trailer}}'
document.getElementById('{{form.synopsis.auto_id}}').value = '{{suggestion.synopsis}}'
document.getElementById('{{form.cast.auto_id}}').value = '{{suggestion.cast}}'
" />
{% endfor %}
So, first of all, how can I declare a function outside. I'm a C developer, sorry for my ignorance.
I've tried to create a script outside, such as
<script>
function foo() {
console.log('Hey');
});
</script>
And invoke it this way:
<img class="catalogue-poster" src="{{ suggestion.poster }}" alt="Portada" onclick="foo()"/>
But this simple thing that works on pure HTML, with django templates does not seem to work...
On the other hand, the real question was, is there a way to access a Django variable passed in render with a js variable?
Such as:
const jsVariable = 'title';
document.getElementById('{{form.jsVariable.auto_id}}').value = '{{suggestion.jsVariable}}'
I have not found any way to accomplish this, maybe there is another great idea!
I have tried one example. where is send a variable from python script and access its value in JavaScript
1) In views.py
from django.shortcuts import render
def home_view(request):
var_name = 'hello'
return render(request, 'home.html', {'var_name':var_name})
2) In html file(home.html)
<html>
<h1>Home Page</h1>
<input type="button" value="Submit" onclick="fun()">
<script>
function fun(){
console.log('hello world '+ '{{var_name}}' );
}
var temp = '{{var_name}}';
console.log(temp + 20);
</script>
</html>
If i click submit button ( hello world hello ) is printed in console.
I stored value of var_name in temp which can be further used.
From your example, it looks you want to programmatically access a Django model's attribute in Javascript.
The main takeaway is that you first need to expose the data structure you want to access (i.e. the model) in Javascript.
Here's a simple, redacted, proof-of-concept you can try.
import json
def my_view(request):
obj = MyModel.objects.get(1)
obj_dict = {
"foo": obj.foo,
"bar": obj.bar,
}
return render(request, 'my_view.html', context={'obj_json': json.dumps(obj_dict)} )
<script>
var obj = {{obj_json}};
var field = 'foo';
console.log(obj[field]);
Check out Convert Django Model object to dict with all of the fields intact for a run-down on options to serialize Django models into dictionaries.
Well, finally I found a solution for both exposed problems.
First of all, the script function I declared was not working because it seems that there is an attribute called autocomplete (see autocomplete HTML attribute)
So, you can not declare a JavaScript function with this name, my fail.
Uncaught TypeError: autocomplete is not a function
Finally, the simple solution I found was passing an array of dicts to the template:
return render(request, 'example.html', {'form': form, 'suggestions': suggestions })
And then in the template:
{% for suggestion in suggestions %}
<img src="{{ suggestion.poster }}" onclick="autocompleteMovie({{suggestion}});" />
{% endfor %}
<script>
function autocompleteMovie(suggestion){
for (let field in suggestion)
document.getElementById('id_' + field).value = suggestion[field]
}
</script
Which, comparing it with the question, really simplifies the problem.
I have a simple 100% working code from CS50 lecture, which represents the usage of Handlebars. Here it is:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script>
<script id="result" type="text/template">
<li>
You rolled:
{{#each values}}
<img alt="{{ this }}" title="{{ this }}" src="img/{{ this }}.png">
{{/each}}
(Total: {{ total }})
</li>
</script>
<script>
// Template for roll results
const template = Handlebars.compile(document.querySelector('#result').innerHTML);
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('#roll').onclick = () => {
// Generate random rolls.
const counter = parseInt(document.querySelector('#counter').value);
const rolls = [];
let total = 0;
for (let i = 0; i < counter; i++) {
const value = Math.floor(Math.random() * 6) + 1;
rolls.push(value);
total += value;
};
// Add roll results to DOM.
const content = template({'values': rolls, 'total': total});
document.querySelector('#rolls').innerHTML += content;
};
});
</script>
</head>
<body>
<input id="counter" type="number" placeholder="Number of Rolls" min="1" value="1">
<button id="roll">Roll</button>
<ul id="rolls">
</ul>
</body>
</html>
When I try to render it in my browser I get "jinja2.exceptions.TemplateSyntaxError: unexpected char '#'".
Obviously the problem is on my computer side. But how to fix it?
I have searched for this problem in the web. One interesting thing I catch was that it is somehow connected with "my server side templating engine". Here is a thread - https://github.com/wycats/handlebars.js/issues/269 . Another guy here (https://github.com/wycats/handlebars.js/issues/1263) says he had similar error because of Pagespeed.
How can I understand which "templating engine" is installed? I have an ordinary Mac and project in virtual environment.
What might be the problem?
This happens because jinja2 reads curly braces as syntax (as variables or block codes).
So, You have to escape jinja in your HTML code.
the methods to do so are following;
The easiest way is to output a literal variable delimiter ({{) is by using a variable expression.
{{ '{{' }}
For bigger sections, it makes sense to mark a block raw. For example, to include handlebars syntax in a template, you can use this snippet:
{% raw %}
<ul>
{{#each vlaues}}
<li>{{ this }}</li>
{{/endeach}}
</ul>
{% endraw %}
For more info check enter link description here
This is my home.html code. I pressed a button in a different .html file. The names are added and stored in an array in the other file and passed thru localStorage and parsed in home.html. Then I looped thru the array to print the names. My issue is on the webpage on the server the names show but after I submit a name it replaces the previous name on the webpage. It's not making a list with one name followed by the other. Is there something I can add with javascript so the names don't keep updating or refreshing? Thanks!
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Home Page </title>
{% extends "navigation.html" %}
{% block content %}
<p> List of Names: </p>
<ul id="List"></ul>
</head>
<body>
<script>
var LL = JSON.parse(localStorage.getItem("newList1"));
document.getElementById("List").innerHTML += "<li>" + LL[LL.length-1] + "</li>";
</script>
</body>
{% endblock %}
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Add Name Page </title>
{% extends "navigation.html" %}
{% block content %}
<p> Add a name: </p>
<form action="home.html">
<input type='text' input name='name' id='addname'>
<input type="button" id="add" value="Submit" onclick="passVal()">
</form>
<ul id="nameList"></ul>
add_name.html
</head>
<body>
<script>
function passVal() {
newList = [];
var newName = document.getElementById("addname").value;
newList.push(newName); //Note: push in javascript assigns value to newList. If I set this to a variable, it would only store the number of elements in that list
localStorage.setItem("newList1", JSON.stringify(newList));
}
</script>
</body>
{% endblock %}
</html>
Thanks for updating your post and including the add_name.html file. The main problem lies there. What you do in the passVal function is to start a new array, then add one value to the array, and then setting the list in the local storage to that array. Therefore the array in the local storage always only has one entry.
Rather than setting the newList variable to an empty array, you should set it to the list of items that are already in the local storage:
add_name.html
<script>
function passVal() {
var previousValue = localStorage.getItem("newList1"); // Get the previous value
var newList;
if(previousValue) {
newList = JSON.parse(previousValue);
} else {
newList = []; // If nothing is in the local storage until now, start with an empty list.
}
var newName = document.getElementById("addname").value;
newList.push(newName);
localStorage.setItem("newList1", JSON.stringify(newList));
}
</script>
</body>
{% endblock %}
Then in the home.html, you need to loop through the values:
var LL = JSON.parse(localStorage.getItem("newList1"));
for(let item of LL) {
document.getElementById("List").innerHTML += "<li>" + item + "</li>";
}
I am passing a data in the form of a dictionary from views.py to results.html in Django framework. The dictionary has the following format
'tweet': (tweet_analysis, tweet_id)
now in results.html, called by the views.py,
I am trying to Embed all the tweets that are passed to results.html, but the following code only displays one embedded tweet.
dicPositive: This is the dictionary containing all the tweets data
{% for tweet, tweet_feel in dicPositive.items %}
<div id="tweet" tweetID="{{tweet_feel.1}}"></div>
<script sync src="https://platform.twitter.com/widgets.js"></script>
<script>
window.onload = (function(){
var tweet = document.getElementById("tweet");
var id = tweet.getAttribute("tweetID");
twttr.widgets.createTweet(
id, tweet,
{
conversation : 'none', // or all
cards : 'hidden', // or visible
linkColor : '#cc0000', // default is blue
theme : 'light' // or dark
})
.then (function (el) {
el.contentDocument.querySelector(".footer").style.display = "none";
});
});
</script>
<!-- <li>{{tweet}} –> {{tweet_feel.0}} –> {{tweet_feel.1}}</li> -->
{% endfor %}
It is because you have used same id for multiple HTMLElements created while looping.
You must add loop counter to id attribute of div and also when
you are fetching it using getElementById inside script tag
{% for tweet, tweet_feel in dicPositive.items %}
<div id="tweet_{{forloop.counter}}" tweetID="{{tweet_feel.1}}"></div>
<script sync src="https://platform.twitter.com/widgets.js"></script>
<script>
window.onload = (function(){
var tweet = document.getElementById("tweet_{{forloop.counter}}");
# Rest of your code
...
</script>
{% endfor %}