Skip to content

Commit f2f25f6

Browse files
docs: document correct unicorn:model pattern for {% for %} loops
1 parent 9ef9a2b commit f2f25f6

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

docs/source/templates.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,57 @@ class HelloWorldView(UnicornView):
6565
[Django models](django-models.md) has many more details about using Django models in `Unicorn`.
6666
```
6767

68+
## Models inside `{% for %}` loops
69+
70+
When iterating over a list with a Django `{% for %}` loop, the loop variable is **not** the same as the component attribute that holds the list. Unicorn syncs `<input>` values by looking up the `unicorn:model` name in the component's serialised data, so the model name must use the **component attribute path** (e.g. `items.0.name`), not the loop variable name (e.g. `item.name`).
71+
72+
Use `{{ forloop.counter0 }}` to build the correct index-based path:
73+
74+
```python
75+
# line_items.py
76+
from django_unicorn.components import UnicornView
77+
78+
class LineItemsView(UnicornView):
79+
items: list = []
80+
81+
def mount(self):
82+
self.items = [{"name": "Widget", "qty": 1}, {"name": "Gadget", "qty": 3}]
83+
84+
def add_item(self):
85+
self.items.append({"name": "", "qty": 0})
86+
```
87+
88+
```html
89+
<!-- unicorn/line-items.html -->
90+
<div>
91+
{% for item in items %}
92+
<div>
93+
<input
94+
unicorn:model="items.{{ forloop.counter0 }}.name"
95+
type="text"
96+
/>
97+
<input
98+
unicorn:model="items.{{ forloop.counter0 }}.qty"
99+
type="number"
100+
/>
101+
</div>
102+
{% endfor %}
103+
<button unicorn:click="add_item">Add row</button>
104+
</div>
105+
```
106+
107+
The key is `items.{{ forloop.counter0 }}.name` this renders to `items.0.name`, `items.1.name`, etc., which Unicorn can resolve directly against the component data.
108+
109+
```{warning}
110+
Using the **loop variable name** in `unicorn:model` (e.g. `unicorn:model="item.name"`)
111+
will **not** work correctly after a re-render. When the component re-renders,
112+
Unicorn tries to look up `item` in the component's data, but `item` is only a
113+
Django template loop variable — it has no corresponding key in the serialised
114+
component state. As a result morphdom will clear the input's value.
115+
116+
Use `items.{{ forloop.counter0 }}.name` instead.
117+
```
118+
68119
## Model modifiers
69120

70121
### Lazy

0 commit comments

Comments
 (0)