New forms - embedding a collection of forms - Symfony2 - javascript

I'm doing the same as explained here: http://symfony.com/doc/current/cookbook/form/form_collections.html
But in my case I want to add new "tags" not manually with clicking on a link, but automatically. I give to my template an array with items and for each of this items I want to add a new form - the number of items should be equal to the number of forms.
If it's possible, I'd prefer a solution like this:
{% for i in items %}
{{ i.name }} {{ form_widget(form.tags[loop.index0].name) }}
{% endfor %}
But how to automatically create objects in the controller, too? It tells me that there is no obeject with index=1, and yes - there isn't, but isn't there a way to create them automatically and not need to create for example 10 empty objects of the same kind in my controller? :(
Another thing I was thinking was something like this:
{% for i in items %}
<ul class="orders" data-prototype="{{ form_widget(form.orders.vars.prototype)|e }}">
{{ i.name }} and here should be a field from the form, for example tag.name
</ul>
{% endfor %}
I suggest that the js given in the cookbook should be changed to do this, but I'm not good in js and my tries didn't do the job.
I tried putting this in the loop:
<script>
addTagForm(collectionHolder);
</script>
and this in a .js file:
var collectionHolder = $('ul.orders');
jQuery(document).ready(function() {
collectionHolder.data('index', collectionHolder.find(':input').length);
function addTagForm(collectionHolder) {
var prototype = collectionHolder.data('prototype');
var index = collectionHolder.data('index');
var newForm = prototype.replace(/__name__/g, index);
collectionHolder.data('index', index + 1);
var $newFormLi = $('<li></li>').append(newForm);
}
});

Assuming that your main class has addTag($tag) method, you can add different 'new' tags to it.
In class Task
public function addTag($tag){
$this->tags[]=$tag;
return $this;
}
In your Controller (assuming 10 tags here)
$task=new Task();
for($i=0;i<10;i++){
$task->addTag(new Tag());
}
$form->setData($task);
In your view
{% for tag in form.tags %}
<ul class="orders">
<li>{{ form_widget(tag.name) }}</li>
</ul>
{% endfor %}
If you don't need the manually click, you can remove the JavaScript part.

Related

How to Give List of Objects IDs and add a click event based on each List IDs in Django

Here in my Django code, I have a list of prices. Now I gave them unique IDs which works well, but when I try to add a click event, the click event only works for only one list item continuously.
{% for price in logistic_branch_pricing %}
<h1 id="select-delivery-location-{{price.id}}"
onclick="calculateDeliveryPrice()">{{ price.id }}-{{price.small_kg_price}}
</h1>
{% endfor %}
{% for price in logistic_branch_pricing %}
<script>
function calculateDeliveryPrice() {
var omo = document.getElementById("select-delivery-location-{{ price.id }}")
omo.classList.add('d-none')
console.log(omo)
}
</script>
{% endfor %}
You don't have to add loop over your <script> tag just pass event keyword inside your javascript onclick function like this
{% for price in logistic_branch_pricing %}
<h1 id="select-delivery-location-{{price.id}}" onclick="calculateDeliveryPrice(event)">{{ price.id }}-{{price.small_kg_price}}
</h1>
{% endfor %}
and inside your javascript do like this
<script>
function calculateDeliveryPrice(e) {
var omo = e.target
omo.classList.add('d-none')
var small_kg_price = omo.textContent.split('-')[1] // return small_kg_price
console.log(omo) // returns element
console.log(omo.id) // returns id of element
}
</script>

How do i create and use variables in django

New to Django and its templates.
I'm trying to set a variable given a specific situation, and that part I think ill be able to do, the code below isn't the exact conditions its just there as a demo. The part im stuck on is how do i create a variable name, and then use that name variable elsewhere. Such as within a div or within a method or anywhere else within the html file, and withing different <Script> tags to run methods and for really any purpose.
demo scenario :
{% for row in table.rows %}
{% if row == 2 %}
{% var name = row.name %}
{% endif %}
{% endfor %}
{% if name %}
<div>{{name}}</div>
{% endif %}
my actual code Im trying to implement:
<script type="text/javascript">
function map_init_basic(map, options) {
var markerClusters = L.markerClusterGroup({ chunkedLoading: true });
{% for row in table.rows %}
var x = "{{ row.cells.x }}"
var y = {{ row.cells.y }}
var m = L.marker([y, x])
m.bindPopup("{{row.cells.first_name}} {{row.cells.last_name}} <br>{{row.cells.chgd_add}}");
m.on("click" , ()=>{
//console.log(`${first_name} ${last_name}`)
{% var first_name = {{row.cells.first_name}} %}
})
//changed row.cells.chgd_add to row.cells.Chgd_add to make sure its matching the table
markerClusters.addLayer(m);
{% endfor %}
markerClusters.addTo(map);
}
{% if first_name %}
console.log("{{first_name}}");
{% endif %}
</script>
Django templates are intended to render html but you are trying to render javascript. It can work but the way you are trying to do it is not a good practice; very soon you won't be able to maintain your code.
If you want to pass data directly from python/django to javascript, an accceptable way to do so is to put the data in a dictionary, translate it to a json string and have it set to a var in your javascript.
in a view:
data = dumps(some_dictionary)
return render(request, 'main/template.html', {'data': data})
in the template:
<script>
var data = JSON.parse("{{data|escapejs}}");
</script>
https://docs.djangoproject.com/fr/3.1/ref/templates/builtins/#escapejs
Alternative: You can use django to generate a widget with data attributes and have a javascript operating on this widget and do whaterever needs to be done.

Adding python variables to jinja counter

I want to add the python variables from flask in the jinja template
Suppose 'a' is a python variable(a list of int values) brought into the jinja template using render_template function from flask :
{%set count = 0%}
{%for element in a%}
{%set count = count + element%}
{%endfor%}
{{ count }}
The value of 'count' should be updated but it still prints 0 on the screen
Can anyone help me?
In the most recent versions, due to scoping rules, your version doesn't work.
Instead, you could do something like this:
{% set count = namespace(value=0) %}
{% for element in a %}
{% set count.value = count.value + 1 %}
{% endfor %}
{{ count }}

How to retrieve Django model id from admin page via javascript

Suppose I have a Django model like this one.
class Car(models.Model):
speed = models.IntegerField()
color = models.CharField(max_length=120)
I registered it in admin via
admin.site.register(Car)
I want to add custom JS button for admin site object view, which will alert value of a color of an instance of a Car model. So when I press it I get something like "The car with id 13 is red"
How can I get id of an object and value of a color field via JavaScript?
You have to extend change_form.html template for you app (https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#overriding-vs-replacing-an-admin-template)
For example I have store app and inside models.py I've put Car model.
Then inside store/templates/admin/store/change_form.html I've put this template:
{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block content %}
{{ block.super }}
<script>
const object = {
pk: {{ original.pk }},
color: '{{ original.color }}',
};
</script>
{% endblock %}
{% block object-tools-items %}
{{ block.super }}
<li>
My button
<script>
const button = document.getElementById('my-button');
button.addEventListener('click', function() {
alert(`The car with ${object.pk} is ${object.color}`);
});
</script>
</li>
{% endblock %}
Admin view:

for loop in html is causing jquery issues

I am writing a webpage about games. In this there is a page in which categories of games should be diplayed, when one is clicked, the games within this category should then appear underneath it.
This is an extract from the html file, I believe the issue is arising when i use the and tag. As they stay constant through each iteration, when i click one category, all categories display their repsective games, rather than just the one selected.
{% if games %}
<h1> Games</h1>
{% for catergory in games %}
<highlight><strong><toggleButton>{{ catergory.0.get_catergory_display }} </toggleButton></strong><highlight>
<ul>
{% for game in catergory %}
<catGames><li><highlight> {{game.name}} : <i>
{% if game.rating != -1 %}
{{game.rating}}
{% else %}
unrated
{% endif %}
</i></highlight></li></catGames>
{% endfor %}
</ul>
<br/>
{% endfor %}
{% else %}
<strong> There are no games present.</strong>
{% endif %}
here is the jquery file
$(document).ready( function() {
$('toggleButton').click(function() {
if ($('catGames').is(':hidden')) {
$('catGames').show();
} else {
$('catGames').hide();
}
});
});
I was wondering if there was an easier solution than having to manually type out each category, and getting rid of the for-loop. It is also causing problems with the jquery which highlights the text being hovered over, lighting all of the categorys and games, rather than just the one being hovered.
You have to specific what is the right <catGames>
Try this different way :
First one :
$('toggleButton').click(function(e) {
const cat = $(e.currentTarget).closest('h1').next('ul').find('catGames');
cat.is(':hidden') ? cat.show() : cat.hide();
});
Second one (best way for me) :
Wrap each catergory with a <div class='catergory'> for example and try this :
$('div.catergory').on('click', 'toggleButton', function(e){
const cat = $(e.delegateTarget).find('catGames');
cat.is(':hidden') ? cat.show() : cat.hide();
});
$(e.delegateTarget) focus the main container whose contain the <catGames>
No the problem is not about loop. Its about how you create elements inside loop and its about how you reference them with onlick even.
so this is one way to fix is:
$(document).ready( function() {
$('toggleButton').click(function() {
if ($(this).parent('highlight').next('ul').find('catGames').is(':hidden')) {
// this way you try to point to the corresponding ul tag next
// to the toggle botton and try to hide and show the whole ul
$(this).parent('highlight').next('ul').find('catGames').show();
} else {
$(this).parent('highlight').next('ul').find('catGames').hide();
}
});
});
So About section you said is there a better solution for the category and opening and closing categories yes there is. Have you checked https://v4-alpha.getbootstrap.com/components/collapse/. I believe you can use the functionality and customized it based on your needs. If you had problem using it let me know.

Categories

Resources