简体   繁体   中英

Passing a variable to an included html modal with Django

I wanted to quickly build a small web app, so I decided to go purely with django and what django offers - template rendering, so no React/Vue or such. The problem that I am having is, that I have some cards, which are being displayed in a for loop (jinja) once the user clicks on a card, a modal shows up and this is where it gets messy.

I want to pass the id of the card, so that I can make a get request and render the data in the modal. The code that I have is:

// index.html

  <div id="machine-cards" class="grid grid-cols-3 gap-4 m-20">
    {% for machine in machines %}
      <div id="card-{{ machine.id }}" onclick="setModalData({{ machine.id }})" class="bg-white shadow-md rounded px-4 pt-4 pb-2 mb-4 transform hover:scale-105 cursor-pointer">
        <div id="card-header" class="flex justify-between">
          <p>Machine number: {{ machine.number }}</p>
          <div id="state"
               class="rounded-full h-4 w-4 {% if machine.status == 1 %} bg-green-500 {% elif machine.status == 2 %} bg-red-500 {% elif machine.status == 3 %} bg-yellow-500 {% else %} bg-gray-500 {% endif %}">
          </div>
        </div>
        <div id="card-body" class="flex justify-center align-center mt-5 mb-5">
          <p>{{ machine.manufacturer }}</p>
        </div>
        <div id="card-footer" class="flex justify-end">
          <p class="text-gray-300 text-sm">Last updated: 28.06.2021</p>
        </div>
      </div>
    {% endfor %}
  </div>
{% include "general/modal.html" %}

<script>
  function setModalData(cardId) {
    // not sure what to do with the cardId :(
    modal.style.display = 'flex';
  }
</script>



// general/modal.html

<body>
<!-- The Modal -->
  <div id="modal" class="hidden justify-center items-center h-full w-full absolute bg-black bg-opacity-50 top-0">
    <!-- Modal content -->
    <div class="bg-white shadow-md rounded px-6 pt-4 pb-8 w-1/2 h-1/2">
      <div class="modal-header flex justify-end">
        <span class="cursor-pointer text-3xl" onclick="modal.style.display = 'none'">&times;</span>
      </div>
      <div class="modal-content flex justify-center items-center ">
        <div class="loader ease-linear rounded-full border-4 border-t-4 border-gray-200 h-12 w-12 mb-4"></div>
      </div>
    </div>

  </div>
</body>
</html>
<script>
  // Get the modal
let modal = document.getElementById("modal");

// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
  if (event.target == modal) {
    modal.style.display = "none";
  }
}
// somehow get the ID, fetch the data and hide the loader
</script>

I know how to do it with React or Vue.js, however, the application is very small and I wanted to quickly prototype it, so I decided to avoid using react/vue or such for now. I was considering giving alpine.js a go as it is smaller compared to the others.

What I have also tried and I hope this is not my best solution, is to move the include block in the for loop and have a hidden modal for every card, which is definitely not the most optimal solution.

I went for the suggestion in the comments by @Swati, which requires jquery (it is also possible to do it without, but in my opinion it is not worth it). The part of the the code that change is

// index.html

  // some unchanged html code

  <div class="machine-modal">
    {% include "general/modal.html" %}
  </div>

<script>
  function setModalData(cardId) {
    $(".machine-modal").html('').load(`{% url 'machine_details' %}?id=${cardId}`);
  }
</script>

The view, which is under the machine_details url will render the modal.html with the needed context

def machine_details(request):
    machine_id = request.GET.get('id', None)

    if machine_id is not None:
        machine_data = Machine.objects.get(machine=machine_id)
        return render(request, 'general/modal.html', {'machineDetails': machine_data})

Lastly, the modal is hidden in an if block and shown only when the data is present

// modal.html
{% if machineDetails %}
// html code
{% endif %}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM