Skip to content

Closes #22522: Render colored badges for Custom Field Choices in tables#22663

Open
studioussagar wants to merge 4 commits into
netbox-community:mainfrom
studioussagar:22522-customfield-colored-badges
Open

Closes #22522: Render colored badges for Custom Field Choices in tables#22663
studioussagar wants to merge 4 commits into
netbox-community:mainfrom
studioussagar:22522-customfield-colored-badges

Conversation

@studioussagar

Copy link
Copy Markdown

Render select and multiselect custom field values as colored badges in table views when a color is defined on the associated choice set.

This aligns table rendering with object detail pages, which already display colored choice values as badges.

Closes: #22522

Render select and multiselect custom field values as colored badges in table views when a color is defined on the associated choice set.

This aligns table rendering with object detail pages, which already display colored choice values as badges.

Related to netbox-community#22522.
@pheus pheus changed the title Render colored badges for custom field choices in tables Closes #22522: Render colored badges for Custom Field Choices in tables Jul 11, 2026
@pheus
pheus requested review from a team and pheus and removed request for a team July 11, 2026 16:41
@pheus

pheus commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

@claude /review Only report on issues of potential concern; we don't need commentary on anything that doesn't require further consideration.

@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Claude finished @pheus's task in 1m 16s —— View job


Review

  • Read the changed file
  • Analyze the diff
  • Post review

Two issues of concern:

1. Separator regression for MULTISELECT fields without colors

The original code used ', ' (comma-space) as the separator for MULTISELECT values. The new code always joins with ' ' (space only), even when no choices have colors:

# Before
return ', '.join(self.customfield.get_choice_label(v) for v in value)

# After — separator changed to space for ALL multiselect fields
return mark_safe(' '.join(parts))

This changes rendering for every MULTISELECT custom field, not just those with colored choices. Fields without a choice set color will now display as "foo bar baz" instead of "foo, bar, baz". The fix should use comma-space as the separator (or only switch to space when any badges are present). Fix this →

2. Unescaped color value in CSS class

color is interpolated directly into the HTML class attribute without escaping:

f'<span class="badge text-bg-{color}">{escape(label)}</span>'

Colors are validated against CustomFieldChoiceColorChoices.values() on save, so in practice this is constrained. However, if anything were to bypass that validation (e.g. direct DB manipulation, a migration edge case), this would allow class attribute injection. Using escape(color) here costs nothing and adds a safety margin. Fix this →


@pheus pheus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for opening this PR!

Could you please take a look at Claude's review comments and either address the points it raised or reply with a short explanation where you think a comment doesn’t apply? That context would be really helpful for the review. Thanks!

@studioussagar
studioussagar requested a review from pheus July 12, 2026 11:37

@pheus pheus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the follow-up work! This still needs a small adjustment to match the existing custom field rendering behavior:

  1. Not every choice is required to define a color. When values are rendered as badges, any choice without an explicit color should fall back to secondary.
  2. For a multiselect field, the rendering mode should apply to the complete set of selected values. If at least one selected value has a color, all selected values should be rendered as badges, without commas between them. Only when none of the selected values has a color should they be rendered as comma-separated plain text.

Could you please update the logic accordingly?

@studioussagar
studioussagar requested a review from pheus July 15, 2026 13:56

@pheus pheus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the follow-up! The overall multiselect behavior now looks right.

There are still a few details to address:

  1. For a single-select field, an uncolored choice should remain plain text. I realize my previous wording could be read as applying the secondary fallback here too, but that fallback is intended only for uncolored values within a multiselect that is already being rendered as badges. Please retain the previous if color: ...; return label behavior for single-select fields.

  2. Please store the unescaped label in parts and escape it only when inserting it into the badge HTML. The label is currently escaped when added to parts and then escaped again in the badge branch, which will display encoded entities for labels containing characters such as & or <. The plain-text branch should return the normal labels and allow the table template to escape them.

  3. Please preserve the existing behavior for an empty multiselect by returning an empty string. self.default here is the column default rather than the table-level display default, and will normally be None.

Could you also add focused tests in netbox/netbox/tests/test_tables.py covering:

  • colored and uncolored single-select values;
  • an empty multiselect;
  • a multiselect with no colored values;
  • a mixed colored/uncolored multiselect, including the secondary fallback and absence of commas;
  • a label containing HTML-sensitive characters, to guard against both missing and double escaping.

@studioussagar
studioussagar requested a review from pheus July 21, 2026 15:03
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

Successfully merging this pull request may close these issues.

Render colored badges for select/multiselect custom fields in list views

2 participants