Skip to content

Commit b6cf14d

Browse files
JohananOppongAmoatengadamghill
authored andcommitted
docs: document how to render TextChoices / choice fields in a Unicorn component
1 parent e3a099a commit b6cf14d

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

docs/source/templates.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,62 @@ component state. As a result morphdom will clear the input's value.
116116
Use `items.{{ forloop.counter0 }}.name` instead.
117117
```
118118

119+
## Rendering choice fields
120+
121+
Django models often use `TextChoices` (or `IntegerChoices`) to constrain a field to a fixed set of values. To render a reactive `<select>` that is bound to a Unicorn component field, expose the choices list as a component attribute and exclude it from the JavaScript context (since the choices are static and do not need to be reactive).
122+
123+
```python
124+
# new_course.py
125+
from django_unicorn.components import UnicornView
126+
from curriculum.models import Course
127+
128+
129+
class NewCourseView(UnicornView):
130+
grade_level = Course.GradeLevel.UNDEFINED
131+
subject = Course.Subject.UNDEFINED
132+
133+
# Static choices — kept out of the JSON state sent to the browser
134+
grade_level_choices = Course.GradeLevel.choices
135+
subject_choices = Course.Subject.choices
136+
137+
class Meta:
138+
javascript_exclude = ("grade_level_choices", "subject_choices")
139+
140+
def save(self):
141+
Course.objects.create(
142+
grade_level=self.grade_level,
143+
subject=self.subject,
144+
)
145+
```
146+
147+
```html
148+
<!-- unicorn/new-course.html -->
149+
<div>
150+
<select unicorn:model="grade_level">
151+
{% for value, label in grade_level_choices %}
152+
<option value="{{ value }}">{{ label }}</option>
153+
{% endfor %}
154+
</select>
155+
156+
<select unicorn:model="subject">
157+
{% for value, label in subject_choices %}
158+
<option value="{{ value }}">{{ label }}</option>
159+
{% endfor %}
160+
</select>
161+
162+
<button unicorn:click="save">Save</button>
163+
</div>
164+
```
165+
166+
Adding the choices to [`Meta.javascript_exclude`](views.md#javascript_exclude) keeps them in the Django template context (so the `{% for %}` loop works) without serialising them into the `unicorn:data` JSON attribute on every render. The `grade_level` and `subject` fields remain fully reactive — Unicorn syncs the selected value back to the component on each change.
167+
168+
```{note}
169+
If you also need validation, set `form_class` on the component to a Django `ModelForm` or `Form`.
170+
Unicorn will validate `grade_level` and `subject` against the form's field definitions when
171+
`$validate` is called or when an action method calls `self.validate()`. See
172+
[validation](validation.md) for details.
173+
```
174+
119175
## Model modifiers
120176

121177
### Lazy

0 commit comments

Comments
 (0)