I'm really new in JavaScript and I have a question:
I need to add inside an inner Html, a Django template if statement that uses a JavaScript variable to compare (in this case the variable is event_id)
I have tried a lot of alternatives after hours and also I have searched with no success.
This is my JS code.
eventClick: function (info) {
var event_id = info.event.id;
$('#exampleModalToggle').modal('show');
selected_group_member.innerHTML = `
{% for reservation in reservations_api %}
{% if reservation.id == ${event_id} %}
<option value="1" selected>{{reservation.id}}</option>
{% endif %}
{% endfor %}
`;
}
with this option, I'm getting this error:
Could not parse the remainder: '${event_id}' from '${event_id}'
and if I change it for {% if reservation.id == + event_id + %}, I'm getting this error: Could not parse the remainder: '' from ''
So, is that possible to do? Do you know how could it work please !!!
I really don't know how to solve it, I really appreciate your help
thanks :)
Something like this could work for you:
eventClick: function (info) {
const reservations = '{{ reservations_api | safe }}';
var event_id = info.event.id;
$('#exampleModalToggle').modal('show');
let innerHtml = '';
reservations.forEach((reservation) => {
if (reservation.id == event_id)
innerHtml += `<option value="1" selected>${reservation.id}</option>`;
});
selected_group_member.innerHTML = innerHtml
}
First of all you create a new javascript variable (called reservations), then you concatenate the desired <option> string into another variable (innerHtml). Finally you set the innerHtml to your selected_group_member.
Update
Added | safe template tag https://docs.djangoproject.com/en/3.2/ref/templates/builtins/#safe as discovered in comments.
Related
I have a Javascript file that enables drop down menus dynamic (i.e. a selection from one drop down impacts the others). I would like to use this file in conjunction with multiple forms but I have hard-coded the starting variables in this file to html elements 'inverter_oem' and 'inverter_model_name'.
In other forms, I will need to reference different objects.
How can I accomplish this?
I would like to create the variables in Javascript this way:
const selecting_dropdown_menu = document.getElementById(variable1_from_flask);
const filtered_dropdown_menu = document.getElementById(variable2_from_flask);
My current approach is to try and pass variables from the Flask route using render_template. (I have also tried other stack overflow solutions but no luck)
#db_queries.route('/db_query_dynamic_form/<form_name>', methods=['GET', 'POST'])
def db_query_dynamic_form(form_name):
# use methods to get form and endpoint for outside loop
if request.method == 'POST':
# inside loop when form complete
return render_template('list.html', result=query_results["filtered_tables"], columns=query_results["column_names"])
# added variable to pass to jinja template
return render_template(form_endpoint["endpoint"], form=form_endpoint["form"], var="value1")
The jinja template form is as follows
% extends "base.html" %}
{% block title %}Inverter Dynamic Search{% endblock %}
{% block heading %}Inverter Dynamic Search{% endblock %}
{% block content %}
<form method="POST">
{{ form.hidden_tag()}}
{{ form.inverter_oem.label }}{{ form.inverter_oem }}<br>
{{ form.inverter_model_name.label }}{{ form.inverter_model_name }}<br>
{{form.submit()}}
{{test}}
</form>
<script>
myVar = {{ var }}
</script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="{{ url_for('static', filename='search_inverter_dynamic.js') }}"></script>
{% endblock %}
However, I dont get a value in the javascript file when I try
console.log(myVar);
Here is the original JScode with the "hardcoded" variables
//acquire inverter_oem value from form
const inverter_oem_select = document.getElementById('inverter_oem');
const inverter_model_name_select = document.getElementById('inverter_model_name');
//add event listener to capture selected oem in dropdown
inverter_oem_select.addEventListener('click', (e) => {
let oem = '../modelNameByOEM//' + e.target.value;
console.log(oem);
getIt(oem);
});
//recover a JSON containing the list of models from a specific oem
async function getIt(input) {
try {
const res = await axios.get(input);
console.log(res.data);
optionHTML = '';
for (let modelName of res.data.modelNameOem) {
//console.log(res.modelName.name);
optionHTML += '<option value="' + modelName.name + '">' + modelName.name + '</option>';
//console.log(optionHTML);
}
inverter_model_name_select.innerHTML = optionHTML;
} catch (err) {
console.log('Could not reach endpoint modelNameByOEM')
console.log(err);
};
}
Jinja does not know that you want to pass a variable inside a JavaScript environment, so it cannot add the quotation marks automatically around a string variable. It just replaces {{ var }} with value1 causing a syntax error. Just add the quotation marks and then you can access myVar inside the JS environment:
<script>
myVar = "{{ var }}"
</script>
Note: if you want to pass a more complex data structure and/or user submitted values, you should look at the tojson filter that safely renders the data.
Hey guys I'm creating a social media messaging app and right now I'm on the basics of creating a button to follow people.
When you click the button, it should change the button from saying "Follow" to "UnFollow". Then the counter for Followers should go up by 1.
So far this is my code and it's not doing anything. I'm not getting any errors but it's also not doing anything at all.
Can someone figure out what I'm doing wrong? Thanks
network.js:
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('followButton').addEventListener('click', () => follow_user());
});
function follow_user() {
const element = document.getElementById('followButton');
element.value = "Un-Follow";
const element2 = document.getElementById('followers');
element2.textContent += 1;
}
profile.html :
{% extends "network/layout.html" %}
{% block body %}
<h2>{{user.username}}'s Profile</h2>
<p id="followers">Followers: {{user.followers}}</p>
<p>Follows: {{user.follows}}</p>
{% for newquery in newqueries reversed %}
<div class="newpost"><p>{{ newquery.body }}</p><p>By: {{ newquery.username }} on: {{ newquery.timestamp }} Likes: {{ newquery.likes }}</p></div>
{% endfor %}
<input type="button" value="Follow" id="followButton">
{% endblock %}
Your first problem is your follower count does not have an ID. You are trying to target it with #followers, but it only has a class .followers.
Your second problem is button inputs don't display textContent. They display their value.
const element = document.getElementById('followButton');
element.value = "Un-Follow";
Try something like this: const element = document.getElementById("followButton").value="Un-Button Follow" i think the value should be Button in between the un and follow i.e un-follow, Note(change it to suit your code)
Check this article here: https://www.permadi.com/tutorial/jsInnerHTMLDOM/index.html
I have a django project that I'm trying to add a custom "online" state to (boolean field in a model). I want to refresh a div periodically to show if a user is now online. The div which is refreshed, with the class button-refresh, is in an included HTML file.
The issue is that the include doesn't work with my for loop in the original HTML file, none of the "professionals" data is retrieved from the server. I'm pretty new to django, my assumption is that the refresh_professionals.html file is retrieved with the ajax request and is entirely separate from the all_professionals.html and then included, without ever being a part of the for loop meaning that the {{ professional.professional_profile.online }} syntax doesn't work.
Any ideas on how to fix this issue? If there is a better way to do this, let me know. Thanks.
all_professionals.html
{% for professional in professionals %}
...
{{ professional.name }}
{% include 'professionals/refresh_professionals.html' %}
...
{% endfor %}
...
{% block postloadjs %}
{{ block.super }}
<script>var global_url = "{% url 'refresh_professionals' %}";</script>
<script src="{% static 'professionals/js/professionals.js' %}"></script>
{% endblock %}
refresh_professionals.html
<div class="col button-refresh">
{% if professional.professional_profile.online is True %}
<p class="custom-button mb-1 w-25 mx-auto">Chat</p>
{% else %}
<p class="custom-button-disabled mb-1 w-25 mx-auto">Unavailable</p>
{% endif %}
<p>{{ professional.price_chat }}/min</p>
</div>
professionals.js
$(document).ready(function(){
setInterval(function() {
$.ajax({
url: global_url,
type: 'GET',
success: function(data) {
$('.button-refresh').html(data);
}
});
}, 5000)
});
urls.py
urlpatterns = [
path('', views.view_all_professionals, name='view_all_professionals'),
path('refresh/', views.refresh_professionals, name='refresh_professionals'),
]
views.py
def view_all_professionals(request):
"""A view to return the professionals page"""
professionals = Professional.objects.all()
languages = Languages.objects.all()
context = {
'professionals': professionals,
'languages': languages,
}
return render(request, 'professionals/all_professionals.html', context)
def refresh_professionals(request):
"""A view to refresh the online button section"""
professionals = Professional.objects.all()
context = {
'professionals': professionals,
}
return render(request, 'professionals/refresh_professionals.html', context)
EDIT
I've followed Daniel's advice and am now returning a JSON object. This is the updated code
professionals.js
$(document).ready(function(){
setInterval(function() {
$.ajax({
url: global_url,
type: 'GET',
success: update_professionals,
});
}, 5000)
});
function update_professionals(response){
// unpack the response (context) from our view function:
var professionals = response.professionals;
// update html:
var i;
for (i = 0; i < professionals.length; i++) {
$('#professional-name' + i).text('professionals.name' + i);
};
};
views.py
def refresh_professionals(request):
"""A view to refresh the professionals section page"""
professionals = Professional.objects.all()
professionals = serializers.serialize("json", professionals)
context = json.dumps({
'professionals': professionals,
})
return HttpResponse(context)
The issue I'm facing now is referencing the professionals data. It's returning uncaught errors. The forloop is necessary because in my HTML I've got a series of IDs with a number attached to the end using a django forloop.counter. Any advice would be appreciated. Thanks.
Okay, lets assume we have a view function like so:
from django.http import HttpResponse
import json
def refresh_professionals(request):
"""A view to refresh the online button section"""
professionals = Professional.objects.all()
# convert to json friendly format:
professionals = ...
context = json.dumps({
'professionals': professionals,
})
return HttpResponse(context)
This assumes professionals now looks something like (the actual structure will obviously be different):
professionals = {"id":1, "name":"Jason"}
Now, in our js file we should have an ajax request like so (wrapped in a setInterval method, etc.):
$.ajax({
url: global_url,
type: 'GET',
success: update_professionals, // reference to an ajax-success function
});
And our success function like so:
update_professionals(response) {
// unpack the response (context) from our view function:
// use JSON.parse() to convert a string to json
var professionals = JSON.parse(response.professionals);
// update html:
$('#professional-name').text(professionals.name)
}
This assumes we have an HTML element like so:
<div id="professionals-name"> Sue </div>
The difference is we are using js to update the HTML on the fly instead of trying to re-render an HTML template likely will require a page refresh.
Can someone show me how to set unique Id for components?
I only know I have to put this code in my default.htm
{% set uid = '{{__SELF__.id}}' %}
how to use it in javascript?
and what is this for?
var avatar_{{uid}} = {{ avatar }};
for example this is my js
$(function(){
$("#tab-close").click(function() {
$("#tab").addClass("hidden");
});
});
How do I set a unique Id for it so that when I duplicate the component both can still work normally without errors?
It might be better to encapsulate your control with a single identifier, like this
<div id="mycontrol{{ __SELF__.id }}">
...
</div>
Then in JavaScript, you can target elements inside:
function initTabs(controlEl) {
var $control = $(controlEl)
$(".tab-close", $control).click(function() {
$(".tab", $control).addClass("hidden");
});
}
The code above targets the class names found only inside the $control container. You would call this function from the markup like so
<script>
$(function(){
initTabs('#mycontrol{{ __SELF__.id }}');
});
</script>
I have a template in Django with a foor loop that looks roughly like this:
{% if items %}
<form method="post" name="managerform" id="managerform" action="">{% csrf_token %}
{{ managerform }}
</form>
{% for item in items %}
<script type='text/javascript'>
var yes = function yes() { manager(function(response) {
if(response && response.status == 'user') {
var object = '{{ item }}'
document.managerform.item.value = object;
document.managerform.preferences.value = "Yes";
document.managerform.submit();
}
else{
authUser(); } });}
</script>
...
<button onclick=yes()>Yes</button>
...
{% endfor %}
Which submits the form, the problem is it always submits the last item from items. I've tried making yes take an argument, aitem, which didn't help because using <button onclick=yes("{{item}}")> failed entirely and doing:
<script>
aitem="{{ item }}"
</script>
<button onclick=yes(aitem)>
just uses the last item from items again.
Is there an obvious solution to this to anyone?
Change your button's HTML to be:
<button onclick='yes("{{item}}");'>Text</button>
And take out the <script> code completely outside of your django conditionals and loops so that it is always available, but change it to be:
var yes = function (item) {
manager(function (response) {
if (response && response.status == 'user') {
var object = item;
document.managerform.item.value = object; // You could combine this and the previous line
document.managerform.preferences.value = "Yes";
document.managerform.submit();
} else {
authUser();
}
});
}
This way, the only thing inside of your django for loop is the button, and each one ends up having a different argument for the yes function. The yes function now accepts a parameter and uses it like you wanted. You'll probably have to modify this to fit your needs though, because your code snippet seems like an example and is not exactly what you have.