miguelgrinberg / turbo-flask

Integration of Hotwire's Turbo library with Flask.
MIT License
301 stars 35 forks source link

Using Turbo-Flask in For Loop #34

Closed WillPowellUk closed 2 years ago

WillPowellUk commented 2 years ago

I have a list of devices that are appended when created. They are then updated every second with the current time like so: image

devices.html

{% for device in devices %}
    <label> {{device.status}} </label>
    <label> {{ device.timeElapsed_s }} </label>
    <label> {{device.numOfCh}} </label>
    <button>Plot</button>
{% end for %}

Previously I updated the whole devices.html every second with the command: turbo.push(turbo.update(render_template('devices.html'), 'load'))

This would update the whole devices which worked very nicely. However this resulted in the animation of the plot button to flicker during a hover as the contents updated - all for a stupid button, here is what I have tried.

I have since removed the button and put it outside of device.html so it does not update. However, I therefore had to remove the {% for device in devices %} part.

I subsequently created DeviceAppender.html which holds the nested devices.html.

DeviceAppender.html

<div class="load-on-append-container" id="load-on-append">
    {% for device in devices %}
        {% include "device.html" %}
       <button>Plot</button>
    {% endfor %}
</div>

device.html

<div class="load-container" id="load">
    <label> {{device.Device_ID}} </label>
    blah blah blah
</div> 

That way I can append deviceAppender.html when a new device is created and update solely the devices.html every second.

Is there a way to update the devices.html using an external For Loop in app.py? I have tried this but it simply overwrites the secondary device:

for device in Manager.devices:
  turbo.push(turbo.replace(render_template('devices.html', device=device), 'load'))

Hopefully I have explained the problem clearly - it's bloody hard to explain. If you inevitably find a simpler solution let me know!

P.S. I did not realise it was your blog post on the last question! @miguelgrinberg, you are a wizard.

miguelgrinberg commented 2 years ago

The problem is that you are always updating the element with id load. Each line in your table must have its own id attribute so that you can push independent updates. Why is it named load anyway? What does it mean in this case?

WillPowellUk commented 2 years ago

Sorry for the slow response.

I am aware that you can push independent updates, however I could not figure a way to update for each device until now.

My solution was to increment through each device and update with a unique target ID for that device like so:

for device in devices:
  targetUpdate = 'update-' + device.Device_ID
  turbo.push(turbo.update(render_template('deviceUpdate.html', device=device), target=targetUpdate))  

where deviceUpdate.html contained the elements that I wanted to target.

When adding new devices I used: turbo.push(turbo.update(render_template('devices.html'), target='update-all-devices')) to update the table of all devices.

As expected, the limitation was not to do with Turbo-Flask but the coder!

Thanks again, Will