Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using knockout.js with django forms?

I am looking to add some structure to my client side code and have been reading about knockout.js. I have been reading the documentations and have a simple question to ask - since knockout requires the user to add a data-bind attributes to the html elements, what is the best way for it to work with django forms, since currently I am using {{ form.as_p }}

I am curious how and where should I form's inputs to the view model (if it is in the form fields in Django, or forfeiting {{ form.as_p }} and type out in html instead.

like image 385
goh Avatar asked May 01 '12 19:05

goh


2 Answers

You can add custom attributes to your fields in the Form's Meta definition with widgets.

class SomeForm(forms.ModelForm):
    class Meta:
        model = SomeModel
        widgets = {'field_name1': forms.Textarea(attrs={'data-bind':'value: field1'}),
                   'field_name2': forms.TextInput(attrs={'data-bind':'value: field2'})}

For example, the first field would be rendered:

<textarea id="id_field_name1" name="field_name1" data-bind="value: field1"></textarea>

Update: as a bonus here is an easy way to change an attribute for every field in a form, for example if they all need a specific class (helpful for other js addons or css styling)

    def __init__(self, *args, **kwargs):
        super(SomeForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs['class'] = 'some_form_field'
            # this could be used in your case if the Django field name is the
            # same as the KO.js field name
            field.widget.attrs['data-bind'] = 'value: %s' % name
like image 80
j_syk Avatar answered Oct 19 '22 21:10

j_syk


Another way is to use django-crispy-forms and define data-bind attributes in the layout:

def __init__(self, *args, **kwargs):
    super(SomeForm, self).__init__(*args, **kwargs)
    self.helper = FormHelper()
    self.helper.layout = Layout(
        Div('field_1',
            Field('field_2', data_bind='value: field_2')),
        HTML("{% if success %} <p data-bind="css: { success: success_flag }">Operation was successful</p> {% endif %}"),
    )

Then in the template you only do:

{% crispy form form.helper %}

and voila.

Cripsy-forms is even more powerful than that and allows you to define your own layout templates etc.

like image 1
Tomasz Zieliński Avatar answered Oct 19 '22 20:10

Tomasz Zieliński