Use a javascript array to display specific HTML divs - javascript

Using django I have a HTML page with a table containing checkboxes:
{% for o in obj %}
<input class='germ_ids' name='{{o.id}}'>
{% endfor %}
<script>
var elements = document.getElementsByClassName("germ_ids");
var ids = [];
for(var i=0; i<elements.length; i++) {
ids.push(elements[i].name);
}
</script>
This has given me an array of specific 'germ ids'. These relate to other django objects I have:
the same .html page:
{% for k, v in add_state_dict.items %}
<div class='{{k.id}}_statement'>
<p>{{v}}</p>
</div>
{% endfor %}
<div class='all_germ'>
<p>{{additional_statement}}</p>
</div>
What I want to achieve is a statement for each germ_id when their checkbox is checked. However when more than one boxes are checked, it makes a concat statement called additional_statement in the 'all_germ' class.
I have hard coded it in in a JSFiddle http://jsfiddle.net/sDsCM/1037/
However I want to use the elements in the array to do this to account for different array values.

You should not be using class names with IDs but instead use class names that categorize your checkboxes. As example I'll be using .checkbox-plus-info. Also, use a data attribute to find the associated statement (unless you can render them inside one div):
{% for o in obj %}
<input class='germ_ids checkbox-plus-info' name='{{o.id}}'
data-info-tag="info-{{o.id}}">
{% endfor %}
{% for k, v in add_state_dict.items %}
<div id='{{k.id}}_statement' class="info info-{{k.obj_id}}">
<p>{{v}}</p>
</div>
{% endfor %}
In the above, k of course needs to contain a reference to the object (its PK/ID). You should have that information in your view and add it to the context. You haven't posted your view/context code but the business logic should mostly be ready while you create the template context, so prepare as much as you can there.
In your JS:
$(".checkbox-plus-info").click(function() {
$(".info").hide(); // hide all
stmtElId = $(this).target.data("info-tag");
$("#" + stmtElId).show();
// check whether something has to be shown when several checkboxes are checked
// e.g. count whether all checkboxes are checked, or other logic
});

Related

Django/Ajax : How to filter a form field's queryset asynchronously?

In a given Django form view, I'd like to filter a field's queryset by an option a user has selected while viewing the form. And I'd like that to happen asynchronously. I've read that AJAX might be what I should use, but I know very little of JS, and I can't make much sense of the information I've read.
The way I see it, I'd like a user to be able to click on one or more checkboxes that would filter 'loot.item_name' by 'item.in_itemlist' or 'item.item_type' (automatically, using onChange or onUpdate or smth?).
Would someone kindly give me some pointers? Cheers,
Here are my models:
models.py
class Itemlist(models.Model):
name = models.CharField([...])
class Item(models.Model):
name = models.CharField([...])
item_type = models.CharField([...])
in_itemlist = models.ForeignKey(Itemlist, [...])
class Loot(models.Model):
item_name = models.ForeignKey(Item, [...])
quantity = [...]
my view,
views.py
def create_loot(request):
# LootForm is a simple ModelForm, with some crispy layout stuff.
form = LootForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
[...]
return render(request, 'loot_form.html', context={'form': form}
and the template,
loot_form.html
{% extends "base_generic.html" %}
{% block leftsidebar %}
/* for each unique itemlist referenced in the items, */
/* make a checkbox that once clicked, filters 'loot.item_name' by the selected option.*/
{% endblock leftsidebar %}
{% block content %}
<h1 class="page-title">Add Loot</h1>
<hr class="page-title-hr">
{% csrf_token %}
{% load crispy_forms_tags %}
{% crispy form form.helper %}
{% endblock content %}
You can create Api based view for your Model
in JavaScript, you can call the the API end and get the data
Ajax code can be something like below
$(document).ready(function () {
setTimeout(function () {
$(document).on('click', '#id', function () {
$.get("./api/v2/end_point?state=" + state, function (data, status) {
var inner_data = data[0].state_count;
change_text.html(inner_data);
});
});
}, 100);
})

Using Javascript to change text Content of a button

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

Django Template - List not rendering properly

I have the following list which is sent to django template using render function: ["9.8 m/s", "9.9 m/s", "1.0 m/s"].
When the list is printed in javascript function, it shows as: ["9.8 m/s", "9.9 m/s", "1.0 m/s"]
I have used the following to print the list: console.log("{{ options }}"); in javascript function.
I have tried iterating over as
{% for option in options %}
console.log("{{ option }}");
{% endfor %}
The above code displays single characters as opposed to printing list elements.
Also tried JSON.parse and JSON.stringify functions in javascript.
The template engine will HTML escape the strings it renders. You can avoid that with the |safe template filter:
var options = {{ option|safe }};
for (var i = 0; i < options.length; i++) {
console.log(options[i]);
}

How to hide Django form fields using JavaScript, Jquery etc

I would like to dynamically
hide form fields. The user should be able to select the component type, which could be a VALVE in which case the user should specify the Kv value and the DI and length fields should be hidden. Or the user could select the PIPE component type in which case the user should specify the inner diameter (DI) and length of the pipe and the k_v field should be hidden.
The model is defined as follows:
class Component(models.Model):
COMPONENT_TYPE_CHOICES = (
(1, 'k_v'),
(2, 'pipe')
)
circuit = models.ForeignKey('circuit.Circuit', related_name='components', on_delete=models.CASCADE)
component_type = models.IntegerField(default=1, choices = COMPONENT_TYPE_CHOICES)
component_name = models.CharField(max_length=200)
branch_number_collectors = models.IntegerField(default=4)
# Hide if component_type==2
k_v = models.FloatField(default=1)
# Hide if component_type==1
DI = models.FloatField(default=0.025)
length = models.FloatField(default=1)
# Calculated properties
branch_volumetric_flow_rate = models.FloatField(default=0)
branch_mass_flow_rate = models.FloatField(default=0)
velocity = models.FloatField(default=0)
reynolds = models.FloatField(default=0)
friction_coefficient = models.FloatField(default=0)
pressure_loss = models.FloatField(default=0)
#classmethod
def create( cls,
circuit,
...,
The forms.py is as follows:
class ComponentForm(forms.ModelForm):
class Meta:
model = Component
fields = [
'component_type',
'component_name',
'branch_number_collectors',
'k_v',
'DI',
'length'
]
The simplified Django template is as follows:
{% block content %}
<form method='POST'> {% csrf_token %}
{{ form.as_p }}
<button type='submit'>Save</button>
</form>
{% endblock %}
first go to django shell and then do the following:
python manage.py shell
from yourapp.yourform import ComponentForm
f = ComponentForm()
print(f.as_p())
this will give you all the id and class names you can use in your javascript or CSS to manipulate.
lets say you want to hide length then you will do:
$(document).ready(function(){
$('#id_length').hide();
})
Ok I solved the problem. When the user selects the PIPE option form the component_type dropdownlist the k_v field is hidden and the DI and length fields are shown. When the user selects the k_v option from the component_type dropdownlist the k_v field is shown and the length and DI fields are hidden.
My Django template is now as follows:
{% extends 'base.html' %}
<script>
{% block jquery %}
// Call hideShow when page is loaded
$(document).ready(function(){
hideShow()
})
// call hideShow when the user clicks on the component_type dropdownlist
$('#id_component_type').click(function(){
hideShow()
});
// The jquery function below hides/shows the k_v, DI and length fields depending on the selected component_type
function hideShow(){
if(document.getElementById('id_component_type').options[document.getElementById('id_component_type').selectedIndex].value == "1")
{
$('#id_length').parents('p:first').hide();
$('#id_DI').parents('p:first').hide();
$('#id_k_v').parents('p:first').show();
}else
{
$('#id_length').parents('p:first').show();
$('#id_DI').parents('p:first').show();
$('#id_k_v').parents('p:first').hide();
}
}
{% endblock %}
</script>
{% block content %}
<form method='POST'> {% csrf_token %}
{{ form.as_p }}
<button type='submit'>Save</button>
</form>
{% endblock %}

Shopify run for loop again after clicking Check-Out button

I'd like to run this for-loop again after clicking the checkout button, to check if the quantity is 2 oder less to set check_nike = true.
is this possible without reloading the side again after the customer set the product quantity on 2?
{% for item in cart.items %}
{% if item.title contains 'nike' %}
{% if item.quantity > 2 %}
{% assign check_nike = false %}
{% endif %}
{% endif %}
{% endfor %}
I have although implemented this in my theme.liquid
$('body').on('click', '[name="checkout"], [name="goto_pp"], [name="goto_gc"]', function() {
if ($('#agree').is(':checked') && {{check_nike}} == true ) {
$(this).submit();
}
else {
if({{check_nike}} == false){
alert("You can't only order two Nike products");
}
else{
document.getElementById("centerbox1").className += " forgottocheck";
}
return false;
}
});
</script>
Thanks :)
You can't use liquid code {{ check_nike }} in a JavaScript for any client side activity. Rather you can try checking the cart.js file of Shopify.
Whenever a product is added to cart use GET as shown in - https://docs.shopify.com/themes/development/getting-started/using-ajax-api#get-cart to see if you specific condition matches.
Going further you can also use localStorage or cookies to reduce the number of GET calls by storing specific cart information locally.

Categories