labd / wagtailstreamforms

What happened when a FormBuilder met a StreamField
http://wagtailstreamforms.readthedocs.io
MIT License
155 stars 79 forks source link

Two or more choice fields #119

Open chingiz opened 5 years ago

chingiz commented 5 years ago

Hi,

I am creating form field which requires Row and Column as in Google's Forms of Multiple Choice Grid.

Specifing Rows as listblock of charfields doesn't show in submission form. However choices which defined by Columns shows because as widget which is set to RadioButtons.

What to do to show Row names too?

stuartaccent commented 5 years ago

Hi @Chingiz

Sorry to hear you're having trouble. Are you able to share your code to help me understand what it is that's going wrong?

Ty Stu

chingiz commented 5 years ago

Yes of course, @stuartaccent,

@register('multiple_choise_grid')
class MultipleChoiceGridField(BaseField):
    field_class = forms.ChoiceField
    widget = forms.widgets.RadioSelect
    icon = 'list-ul'
    label = 'Multiple Choice Grid'

    def get_options(self, block_value):
        options = super().get_options(block_value)
        choices = [(c.strip(), c.strip()) for c in block_value.get('choices')]
        options.update({'choices': choices})
        return options

    def get_rows(self, block_value):
        options = super().get_options(block_value)
        rows = [(c.strip(), c.strip()) for c in block_value.get('rows')]
        options.update({'rows': rows})
        return options

    def get_form_block(self):
        return blocks.StructBlock([
            ('label', blocks.CharBlock()),
            ('help_text', blocks.CharBlock(required=False)),
            ('required', blocks.BooleanBlock(required=False)),
            ('rows', blocks.ListBlock(blocks.CharBlock(label="Row"))),
            ('choices', blocks.ListBlock(blocks.CharBlock(label="Columns")))
        ], icon=self.icon, label=self.label)

This code works. I wanted to reproduce google form's multiple choice form field. But on preview I do not see the rows which I set in cms. Also I would liked to design it.

Question n1: How can I show rows also? Question n2: How to control fields id and class names.

stuartaccent commented 5 years ago

Yeh the problem will be that the form knows nothing of the rows other than it will be being passed into your column fields as a rows attribute within the options.

If you are wanting to show a row and column field I would either create these as two separate fields or alternatively use Django's MultiValueField with 2 fields and get the value back as [row, column] or similar. https://docs.djangoproject.com/en/2.1/ref/forms/fields/#multivaluefield.

When I get a second I will try to come up with a working example and add it to the wiki. We have used something similar with addresses. If you get one in the mean time would be great to have the example for others to see.

the id is currently just the label as a slug. There is no hook to intercept it that I know of.

class names I would prob add widget = forms.widgets.RadioSelect(attrs={'class': 'foo'}) or by something similar.

chingiz commented 5 years ago

I'm sorry for late response, but I am stil unable to implement things that you have mentioned.

Changed field_class to MultiValueField, and added

@register('multiple_choise_grid')
class MultipleChoiceGridField(BaseField):
    field_class = MultiValueField
    widget = forms.widgets.RadioSelect
    icon = 'list-ul'
    label = 'Multiple Choice Grid'

    def get_options(self, block_value):
        options = super().get_options(block_value)
        choices = [(c.strip(), c.strip()) for c in block_value.get('choices')]
        rows = [(c.strip(), c.strip()) for c in block_value.get('rows')]
        options.update({'rows': rows})
        options.update({'choices': choices})
        print(options)
        return options

And able to see rows, but there is a problem with passing rows as: {'label': 'Testing Multiple Choice Grid', 'help_text': '', 'required': False, 'initial': None, 'rows': [('Row1', 'Row1'), ('Row2', 'Row2'), ('Row3', 'Row3')], 'choices': [('C1', 'C1'), ('C2', 'C2')]}

Gives this exception: __init__() missing 1 required positional argument: 'fields'

Can you please help me to resolve this issue? @stuartaccent