Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rendering text choices in a UnicornView #324

Open
WVandergrift opened this issue Dec 23, 2021 · 3 comments
Open

Rendering text choices in a UnicornView #324

WVandergrift opened this issue Dec 23, 2021 · 3 comments
Assignees

Comments

@WVandergrift
Copy link

I have a UnicornView that I'm using to display a form with multiple fields that have TextChoices. What's the best way to do this with Unicorn? In a standard django view, I'd use the ModelForm to handle rendering the form field, but I'm not sure that approach would work without requiring reloading the page.

NewCourseView:

from django_unicorn.components import UnicornView
from curriculum.forms import NewCourseForm


class NewCourseView(UnicornView):
    form_class = NewCourseForm

    title = ""
    grade_level = ""
    subject = "" 

NewCourseForm:

from django.forms import ModelForm
from .models import Course


class NewCourseForm(ModelForm):
    class Meta:
        model = Course
        fields = ['title', 'grade_level', 'subject']

Course Model:

class Course(models.Model):

    class GradeLevel(models.TextChoices):
        UNDEFINED = 'U', "UNDEFINED"
        KINDERGARTEN = 'K', "KINDERGARTEN"
        FIRST_GRADE = '1st', "FIRST_GRADE"
        SECOND_GRADE = '2nd', "SECOND_GRADE"
        NINTH_GRADE = '9th', "NINTH_GRADE"

    class Subject(models.TextChoices):
        UNDEFINED = "Undefined", "UNDEFINED",
        MATH = "Math", "MATH",
        SCIENCE = "Science", "SCIENCE"

    title = models.CharField(max_length=256)
    grade_level = models.CharField(
        max_length=10,
        choices=GradeLevel.choices,
        default=GradeLevel.UNDEFINED
    )
    subject = models.CharField(
        max_length=25,
        choices=Subject.choices,
        default=Subject.UNDEFINED
    )
@adamghill adamghill self-assigned this Dec 23, 2021
@adamghill
Copy link
Owner

Hey, this is a good question! Usually I don't use Django Forms/ModelForms to render the widget HTML so I haven't thought about how Unicorn could be used in this way too much. I would typically do something similar to https://www.django-unicorn.com/docs/validation/ like this:

<!-- new-course.html -->
<div>
  <input unicorn:model="title" type="text" /><br />
  <input unicorn:model="grade_level" type="text" /><br />
  <input unicorn:model="subject" type="text" /><br />

  <button unicorn:click="$validate">Validate</button>
</div>

However, if you want the form to be rendered automatically by Django you could do something like this:

class NewCourseView(UnicornView):
    form_class = NewCourseForm

    def form(self):
        return self.form_class()
{{ form }}

However, the above won't be "integrated" with Unicorn in any way. What might be helpful is if you show me what your ideal HTML template would look like and what you would expect and I can try to figure out if it's possible with some updates to Unicorn!

@WVandergrift
Copy link
Author

Thanks for the quick reply @adamghill!

My main thought behind wanting to use django's model form was for its convenience. For example, django will automatically populate a select elements options with the choices defined in the model.

As far as a potential implementation goes, one possibility might be to extend Django's different model fields and add a binding or model attribute that would determine what attribute on your UnicornView would be updated.

grade_level = models.CharField(
        max_length=10,
        choices=GradeLevel.choices,
        default=GradeLevel.UNDEFINED
        model=grade_level

@adamghill
Copy link
Owner

Yep, I gotcha. If you don't use the built-in rendering, you could manually create the component something like this:

class NewCourseView(UnicornView):
    form_class = NewCourseForm
    course = Course()

    def form(self):
        return self.form_class(instance=self.course)

    def save(self):
        self.course.save()
<select unicorn:model="course.grade_level">
    {% for grade_level in form.Meta.model.GradeLevel.choices %}
    <option value="{{ grade_level.0 }}">{{ grade_level.1 }}</option>
    {% endfor %}
</select>

<!-- other selects here -->

Where I'm a little stuck is I could write some JavaScript so that the Django form rendering is integrated with Unicorn, but it would tricky. For example, if some form fields should be defered and others lazy and others debounced, I need a way to handle any modifier for the Unicorn model attributes.

There might be a way to do this elegantly with form widgets attrs (https://docs.djangoproject.com/en/4.0/ref/forms/widgets/#styling-widget-instances) or the new form template in 4.0 (https://docs.djangoproject.com/en/4.0/ref/forms/renderers/#overriding-built-in-form-templates) that I could look into more if you'd like.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants