Opened 5 weeks ago

Last modified 2 weeks ago

#28712 assigned New feature

Add ability to apply separate attributes to ChoiceWidget options

Reported by: Stephen Swatman Owned by: Stephen Swatman
Component: Forms Version: master
Severity: Normal Keywords: ChoiceWidget
Cc: Tim Martin Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

For ChoiceWidget objects the list of options is created in the create_option method. Currently, options created by this method can either inherit attributes from the parent widget or have no attributes at all but there is no way to separately assign attributes to options as far as I am aware. I would like to suggest introducing the ability to specify separate option attributes in the ChoiceWidget constructor which are applied only to the options in that widget.

Even more powerful would be the ability to pass callables as attribute values which could dynamically compute attributes based on option attributes such as names and values.

Change History (12)

comment:1 Changed 5 weeks ago by Tim Graham

Easy pickings: unset

Could you describe your use case in more detail? Is there a reason that overriding ChoiceWidget.create_option() wouldn't work?

comment:2 in reply to:  1 Changed 4 weeks ago by Stephen Swatman

Replying to Tim Graham:

Could you describe your use case in more detail? Is there a reason that overriding ChoiceWidget.create_option() wouldn't work?

Web developers may want to individually style each option in a ChoiceWidget, be it by adding CSS classes or style attributes. This may be done to add images to such a widget to make it more appealing to the user. Developers may also want to add ARIA properties to the options or add additional information to work with them via JavaScript.

It would absolutely be possible to override the ChoiceWidget class and modifying the create_option() method. I imagine, however, that this is a common enough use case to warrant a simpler method of doing this. Here are some people on StackOverflow having the same issue:

comment:3 Changed 4 weeks ago by Stephen Swatman

Has patch: set
Owner: changed from nobody to Stephen Swatman
Status: newassigned

comment:4 Changed 4 weeks ago by Tim Graham

As for the case of styling, wouldn't it involve less markup to set a class on the <select> and use a CSS selector (e.g. select.super option {...}) for that? If anything, I'd think we'd want a way to specify a different attribute value for each <option> value -- setting the same key/value on every <option> doesn't seem like something to encourage.

comment:5 in reply to:  4 Changed 4 weeks ago by Stephen Swatman

Replying to Tim Graham:

As for the case of styling, wouldn't it involve less markup to set a class on the <select> and use a CSS selector (e.g. select.super option {...}) for that? If anything, I'd think we'd want a way to specify a different attribute value for each <option> value -- setting the same key/value on every <option> doesn't seem like something to encourage.

You're right that the implementation in the PR was not very powerful. I have now expanded the PR to allow for callable attribute values. When a callable is passed as an attribute value it is separately evaluated for each option and the returned value is used. This would allow developers a lot of control over the attributes of each option.

Last edited 4 weeks ago by Stephen Swatman (previous) (diff)

comment:6 Changed 3 weeks ago by Tim Graham

I still don't find the example in the documentation particularly compelling. Instead of adding CSS classes for that case, I would use CSS [value=x] selectors.

comment:7 in reply to:  6 Changed 3 weeks ago by Stephen Swatman

Replying to Tim Graham:

I still don't find the example in the documentation particularly compelling. Instead of adding CSS classes for that case, I would use CSS [value=x] selectors.

The particular case that inspired me to create this issue is that I had a model and I wanted to create a choice widget for that model. I wanted each option to be styled such that it had a background image served from a different server such that I needed to construct an attribute of the form style="background-image: url(https://somewhere.com/images/[id].png)" where the ID was the object's ID. The problem was solved by extending the Select class and overriding the create_option() method. However, I feel it would have been more easily solved had the pull request I created been in place.

Still, I absolutely understand if you think this is too niche. Thus, if I haven't convinced you please feel free to close the issue!

Last edited 3 weeks ago by Stephen Swatman (previous) (diff)

comment:8 Changed 3 weeks ago by Tim Graham

Patch needs improvement: set
Triage Stage: UnreviewedAccepted

I think the functionality could be useful but it would be nice to document a more useful use case. Also, the patch documents the new functionality as Select.opt_attrs but the implementation is on ChoiceWidget. Other classes such as RadioSelect inherit from ChoiceWidget, not from Select.

comment:9 Changed 3 weeks ago by Stephen Swatman

Patch needs improvement: unset

I have made an attempt to address your concerns: a more compelling example is given and I have placed it in a more sensible section to cover the entire ChoiceWidget family.

Jenkins is indicating non-passing tests but logs and the fact that only minor documentation changes have been made and that that the docs test still passes lead me to believe this is not an issue with the pull request.

comment:10 Changed 3 weeks ago by Tim Martin

Cc: Tim Martin added
Patch needs improvement: set

I added a couple of minor comments on the documentation in the pull request.

comment:11 in reply to:  10 Changed 3 weeks ago by Stephen Swatman

Patch needs improvement: unset

Replying to Tim Martin:

I added a couple of minor comments on the documentation in the pull request.

Thank you! I have amended the mistakes you pointed out.

comment:12 Changed 2 weeks ago by Bjorn Kristinsson

I ran into a case the other day where this would have been extremely useful. I needed to show a select with all options visible, but depending on the user's permissions some of the options needed to be disabled. This can be achieved by setting the disabled attribute, but since there was no way to do that per option, I had to roll my own.

Looks like this would solve that, and if you're still looking for an example to use in the docs, maybe you could show how to disable options?

Note: See TracTickets for help on using tickets.
Back to Top