modal opening only for the first for loop element? - javascript

I have my for loop in Django such as its only opening the modal for the first element and nothing happens for other elements.
This is my HTML file it display all elements in a table with delete button. When clicking delete button a modal is opened but it is opened for the first element only, what should I change in this?
<table>
{% for card in cards %}
<tr class="record">
<td>{{card.number}}</td>
<td>
<button
class="hover:bg-gray-500 duration-500"
id="delete-btn"
>
</button>
<div
class="
fixed
flex
justify-center
items-center
hidden
"
aria-labelledby="modal-title"
aria-modal="true"
id="overlay"
>
............. #some lines of code
<div
class="
bg-gray-50
px-4
py-3
sm:px-6 sm:flex sm:flex-row-reverse
"
>
<a
href="{% url 'p:delete-card' card.id %}"
id="delbutton"
>
<button
type="button"
class="
w-full
inline-flex
justify-center
"
>
Delete
</button>
</a>
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
My js to open the modal on button click
window.addEventListener('DOMContentLoaded',() =>{
const overlay = document.querySelector('#overlay')
const delbtn = document.querySelector('#delete-btn')
const toggleModal = () => {
overlay.classList.toggle('hidden')
overlay.classList.add('flex')
}
delbtn.addEventListener('click',toggleModal)
})

I solved it like this with the help of Data in Django for loop {% for %} not loading for Modal
I changed the id of all the buttons like this and added delete-button class!
<button class="hover:bg-gray-500 duration-500 delete-button" id="delete-btn_{{card.id}}">
</button>
Like this added card.id in overlay too.
My Jquery:
$(".delete-button").click(function() {
var id = $(this).attr("id").split("_")[1]
$(`#overlay_${id}`).show();
});

Every modal should have a different id in the for loop.
You can use something like id="modal{{card.id}}"
Then select that id
Does that help you?

Related

Vue make each v-for have own version of variable

i am looping through an array displaying songs I have uploaded into firebase. I am giving the user a button to edit the name of the song if they press the edit button. When button is pressed it show to edit details, however, except of only the one object expanding all of them expand to edit. How can I give each object its own version of the showForm Bool thanks.
Displaying songs:
<div v-for="song in watchSongs" :key="song.docID">
<div class="mt-[10px] border-solid border-2 border-gray-400 rounded-lg p-[5px] min-h-[40px]">
<p class="font-bold float-left">{{song.modifiedName}}</p>
<img #click.prevent="showForm = !showForm" src="#/assets/edit.png" alt="" class="w-[20px] float-right hover:cursor-pointer">
<img src="#/assets/close2.png" alt="" class="w-[20px] float-right hover:cursor-pointer">
<div v-if="this.showForm" class="pt-[30px]">
<p>song title</p>
<input type="text" placeholder="Enter Song Title" class="w-[100%] h-[30px] pl-[5px] mt-[10px] bg-transparent border-[1px] border-solid border-gray-300">
<p>Genre</p>
<input type="text" placeholder="Enter genre" class="w-[100%] h-[30px] pl-[5px] mt-[10px] bg-transparent border-[1px] border-solid border-gray-300">
<div class="flex mt-[20px] mb-[10px]">
<button class="bg-green-500 rounded-md w-[70px] mr-[5px]">Submit</button>
<button class="bg-gray-400 rounded-md w-[70px]">Go back</button>
</div>
</div>
</div>
The data:
export default {
name:"AppUploadDetails",
props: ['songs'],
data(){
return{
showForm:false,
}
},
computed:{
watchSongs(){
return this.songs;
}
}
}
Fixed by changed the v-if to v-if="song.showForm" and the click to #click.prevent="song.showForm"
Use an object to store your loop items, with the key being the docID.
Something like this:
showForm: {}
click.prevent="showForm[song.docID] = !showForm[song.docID]

Reference a confirmation window from forloop

I've been trying to create a popup delete confirmation overlay from a forloop. I can't make it work or define which ids or how to pass identifiers for the overlay.
I got this, but it only refers the first element of the loop. I tried serialize the ids with the element pk (myNavRef{{ref.pk}}), but doesn't work
{% for ref in perf_bim.referenciapredio_set.all %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<th>{{ref.rol_fk.rol}}</th>
<th>{{ref.rol_fk.dir}}</th>
<td><img src="{% static 'arrow.png' %}" height=20 alt=""></td>
<td><button onclick="openNavRef()" type="button" class="btn btn-outline-dark btn-sm"><img src="{% static 'trash.svg' %}" alt="" height=15 ></button><br></td>
</tr>
<div id="myNavRef" class="overlay">
<div class="fontformat"style="padding-top:250px;width:40%;margin:auto;">
<div class="overlay-content">
Eliminar Referncia de Predio Rol: {{ref.rol_fk.rol}}
<br>
Cancelar
</div>
</div>
</div>
{% endfor %}
<script>
function openNavRef() {
document.getElementById("myNavRef").style.display = "block";
}
function closeNavRef() {
document.getElementById("myNavRef").style.display = "none";
}
</script>
thanks!!
If you want to display the corresponding div then you can define the div with unique id. Then you can show corresponding div with the provided id of the element.
First set your div element with unique id as
<div id="myNavRef{{ref.pk}}" class="overlay">
Then on your button element onclick pass the same id as
<button onclick="openNavRef('{{ref.pk}}')" type="button" class="btn btn-outline-dark btn-sm">
Also for your close button as
Cancelar
Then in your javascript
<script>
function openNavRef(id) {
document.getElementById("myNavRef" + id).style.display = "block";
}
function closeNavRef(id) {
document.getElementById("myNavRef" + id).style.display = "none";
}
</script>

How can I re-run a Django For Loop inside a HTML Div using Javascript on Click Event

I have a HTML div like this,
<div class="coment-area ">
<ul class="we-comet">
{% for j in comment %}
<div id="delete_comment{{j.id}}" class="mt-3">
{% if j.post_id.id == i.id %}
<li >
<div class="comet-avatar">
{% if j.user_id.User_Image %}
<img class="card-img-top" style=" vertical-align: middle;width: 50px;height: 50px;border-radius: 50%;" src= {{ j.user_id.User_Image.url }} alt="">
{% else %}
<img class="card-img-top" style=" vertical-align: middle;width: 60px;height: 60px;border-radius: 50%;" src="static\images\resources\no-profile.jpg">
{% endif %}
</div>
Inside of it is a For Loop that is executed when the page is first loaded.
Below this For Loop is a Comments Button
<div >
<button type="submit" onclick="comment_save(event,{{i.id}})" class= "my-2 ml-2 px-2 py-1 btn-info active hover:bg-gray-400 rounded ">Comment</button>
</div>
</div>
</li>
</ul>
</div>
Whenever this button of Comments is clicked, a function in Javascript is called which is defined below,
function comment_save(event,post_id)
{
var comment_value=$("#comment_value"+post_id).val();
var user_id=$("#comment_user_id"+post_id).val()
postdata={
"comment_value":comment_value,
"user_id":user_id,
"post_id":post_id
}
SendDataToServer("readmore",postdata,function()
{
alert()
})
$("#comment_value"+post_id).val(" ")
<! --- document.location.reload().. Something here that refresh that for loop --->
}
What I want is this that whenever the button is clicked, it re-executes that for Loop inside my main div without having to refresh the page. I have been trying to do this for two days but could not find any solution to this. Can anyone help me in doing this?
The Django Templating Language is executed server-side. That means the client (browser, running Javascript) has no access to it whatsoever.
Some of your options are:
Do everything back-end: Re-render the template (which you said don't want to do).
Do everything front-end: You could have your view function return the data used in your template loop and re-implement it in your front-end (but that makes the original template loop kind of pointless).
Hybrid: Return the data for only the new comment in your response and add it to the list with Javascript.

How to add classes to an element outside of AlpineJS element

I have a simple question but it's driving me mad to work out.
I'm using AlpineJS to show and hide content.
Normally with alpine, the button and content will be in the same element, but here I have it outside of it. This works.
But I cannot add classes to both the button and content div when the content is open or closed.
Can anyone guide me please.
<!-- button -->
<div class="mt-4" x-data="{id: 1}">
<button
#click="$dispatch('open-dropdown',{id})"
type="button"
class="bg-white hover:bg-gray-50"
:class="{ 'bg-green-400': open, 'bg-gray-200': !(open) }">
I'm the button
</button>
</div>
<!-- popup 1 -->
<div x-data="{ open: false }"
x-show="open"
#open-dropdown.window="if ($event.detail.id == 1) open = true"
#click.away="open = false">
<div
class="bg-white hover:bg-gray-50"
:class="{ 'bg-green-400': open, 'bg-gray-200': !(open) }">
I'm the content
</div>
</div>
For this you can move the open state inside the global Alpine.js' $store object that is accessible for all component on the page.
<!-- button -->
<div class="mt-4" x-data="{id: 1}">
<button #click="$dispatch('open-dropdown',{id})"
type="button"
class="bg-white hover:bg-gray-50"
:class="{ 'bg-green-400': $store.open, 'bg-gray-200': !($store.open) }">
I'm the button
</button>
</div>
<!-- popup 1 -->
<div x-data
x-show="$store.open"
#open-dropdown.window="if ($event.detail.id == 1) $store.open = true"
#click.away="$store.open = false">
<div class="bg-white hover:bg-gray-50"
:class="{ 'bg-green-400': $store.open, 'bg-gray-200': !($store.open) }">
I'm the content
</div>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('open', false)
})
</script>
Since our open state in the store is a simple value, we can just replace every open with $store.open. Note that the popup 1 component still requires an empty x-data attribute.

loading foreign key data in drop down select name too slow

I'm trying to show foreign key data as a drop down list, but we have a big data, the problem is it takes too long to load page that has the drop down field with the foreign key, is there a way to load it part by part?
here is my models.py
class Vistor(models.Model):
admin = models.ForeignKey(User,on_delete=models.PROTECT,default=1)
full_name = models.CharField(max_length=150,verbose_name=_('full name'))
dob = models.DateField(max_length=14,verbose_name=_('dob'))
city = models.ForeignKey(City,on_delete=models.CASCADE,verbose_name=_('city'))
class Meta:
constraints = [
models.UniqueConstraint(fields=['full_name','dob','city'],name='full_information')
]
def __str__(self):
return f'{self.full_name} - {self.city} - {self.dob}'
and here is my views.py
def add_new_post(request):
...
context = {
'form':form,
'room_number':room_number,
'cities':City.objects.all(),
'all_guests':Vistor.objects.all().order_by('-pk'), #the problem is here, has a big data
}
return render(request,'booking/add_booking.html',context)
and here is my templates
<div class="grid md:grid-cols-10 md:gap-5 child_formset_row" id="guests_no-${form_no}">
<div class="col-span-5 groupinput relative bglightpurple mt-2 rounded-xl">
<label class="text-white absolute top-1 mt-1 mr-2 text-xs">{% trans "full information" %}</label>
<select name="guestinfo-0" id="guestinfo-0" class="visitors w-full pr-2 pt-6 pb-1 bg-transparent focus:outline-none text-white">
<option value="-----">------</option>
{% for c in all_guests %}
<option value="{{ c.full_name }} - {{c.city}} - {{c.dob | date:'Y-m-d'}}">{{ c.full_name }} - {{c.city}} - {{c.dob | date:'Y-m-d'}}</option>
{% endfor %}
</select>
</div>
<div class="col-span-4 groupinput relative bglightpurple mt-2 rounded-xl">
<label class="text-white absolute top-1 mt-1 mr-2 text-xs">{% trans "reason" %}</label>
<input type="text" name="reason-0" id="reason-0" value="" required class="w-full pr-2 pb-1 pt-6 bg-transparent focus:outline-none text-white">
</div>
<button type='button' class="col-span-1 flex items-center justify-center groupinput relative bglightpurple mt-2 rounded-xl" onclick="remove_form(this,${form_no})"><i class="text-red-600 far fa-trash-alt"></i></button>
</div>
is there a way to load it part by part please ?
thank you so much for your helps ..
You can use django-autocomplete-light along with leveraging Django forms to display that element.
This gives a searchable as well as scrollable dropdown that loads your data with a pagination type of concept.

Categories

Resources