Skip to content

Create select_taxons admin form component - #6653

Open
benjaminwil wants to merge 3 commits into
solidusio:mainfrom
benjaminwil:product-taxon-select-component
Open

benjaminwil wants to merge 3 commits into
solidusio:mainfrom
benjaminwil:product-taxon-select-component

Conversation

@benjaminwil

@benjaminwil benjaminwil commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This pull request creates a bespoke component for selecting taxons from a list of all of a store's taxons. This resolves #6643.

It also starts using the new component in two existing templates.

A screenshot showing four variants of the taxon select component: single select, single select with pre-filled options, multi-select, and multi-select with pre-filled options

Checklist

Check out our PR guidelines for more details.

The following are mandatory for all PRs:

The following are not always needed:

  • 📖 I have updated the README to account for my changes.
  • 📑 I have documented new code with YARD.
  • 🛣️ I have opened a PR to update the guides.
  • ✅ I have added automated tests to cover my changes.
  • 📸 I have attached screenshots to demo visual changes.

Footnotes

  1. There is a JavaScript console error hard-coded in English. The intended audience is developers, though, not customers. ↩

Comment thread admin/app/components/solidus_admin/ui/forms/field/component.rb Outdated
@codecov

codecov Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.48%. Comparing base (6f5b2b9) to head (98aa43a).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6653   +/-   ##
=======================================
  Coverage   92.47%   92.48%           
=======================================
  Files        1065     1066    +1     
  Lines       21541    21558   +17     
=======================================
+ Hits        19921    19938   +17     
  Misses       1620     1620           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@benjaminwil
benjaminwil force-pushed the product-taxon-select-component branch 10 times, most recently from 2899eff to d23c1f4 Compare September 29, 2026 23:04
@benjaminwil
benjaminwil marked this pull request as ready for review September 30, 2026 01:49
@benjaminwil
benjaminwil requested a review from a team as a code owner September 30, 2026 01:49

@tvdeyen tvdeyen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should use the configured routes by using the routes helpers we have available in components, via the helpers proxy.

Comment thread admin/app/components/solidus_admin/ui/forms/field/component.rb Outdated
Comment thread admin/app/javascript/solidus_admin/utils.js Outdated
@benjaminwil
benjaminwil force-pushed the product-taxon-select-component branch 2 times, most recently from d23c1f4 to c77f9c6 Compare September 30, 2026 15:25
@benjaminwil
benjaminwil requested a review from tvdeyen September 30, 2026 15:26
@benjaminwil

Copy link
Copy Markdown
Contributor Author

I still think this is worth reviewing right now, but I have to go back and re-evaluate the tests due to timing issues.

There are indications that the remote data is not being loaded fast enough for the feature tests to fail. We're not waiting in quite the right ways.

@tvdeyen tvdeyen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looking good.

<%= render component("ui/forms/field").select_taxons f,
:parent_id,
include_blank: t(".none"),
multiple: false %>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be the default anyway, no?

Suggested change
multiple: false %>
%>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

From a data perspective, I thought that multiple: true makes sense as a default. Since you'd almost always want a collection of taxons to be associated with something.

But maybe from a developer experience perspective you're more correct.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@tvdeyen @jarednorman I don't feel strongly about this, but I've left it with a multiple: true default for now. This felt like the natural thing to do, due to the method name (.select_taxons plural).

If you all feel strongly in the other direction, I can change this.

@benjaminwil
benjaminwil force-pushed the product-taxon-select-component branch from c77f9c6 to f808334 Compare October 1, 2026 18:55
@benjaminwil

Copy link
Copy Markdown
Contributor Author

There are indications that the remote data is not being loaded fast enough for the feature tests to fail. We're not waiting in quite the right ways.

I was wrong. The issue was that using URL helpers via SolidusAdmin::Engine needed to be explicitly configured for the test environment. I have added a commit that does this.

errors:,
label:,
multiple: true,
src: SolidusAdmin::Engine.routes.url_helpers.pretty_names_taxons_url,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In my local testing this still caused issues outside of tests because the host wasn't set because this doesn't have a request context, but this complicates the JS.

What if we just add a taxon select component that renders our select component from the view layer and avoids all of this complexity.

@benjaminwil benjaminwil Oct 4, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm not opposed to doing it that way.

But maybe it's worth discussing more? I feel like all of this is pointing to the fact that it's not easy enough to create select components that use remote data sources. Do we want to (and do we want application developers to) have to write view partials every time we (they) want a mildly complex select component in the admin interface?

I think the complexity is reasonably reduced if we can pass paths (rather than URLs) to the solidus_select.js we've built on top of Tom Select.

cc @tvdeyen

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't have a strong preference either way. If accepting paths makes stuff easier and is reasonably easy to do, that approach has my blessing.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes. What Jared says.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@jarednorman @tvdeyen I added a new commit that tackles this issue by allowing the use of path helpers.

I chose this route because:

  1. Currently the component is just a class method on the Form::Field::Component, so there would be some indirection and a lot more code to make a new component and component template. (Said another way: less code this way.)
  2. I think I was able to offset the complexity of getting URLs in a reasonable way, after all. See the Apply host URL to solidus_select data-srcs commit.

Let me know what y'all think.

@benjaminwil
benjaminwil requested a review from tvdeyen October 7, 2026 15:45
@benjaminwil
benjaminwil force-pushed the product-taxon-select-component branch from f808334 to 98bfa7d Compare October 22, 2026 21:20
else
within(dropdown) { expect(page).to have_css(".option", minimum: 1) }
control.click
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think the second half of this branch is used in this PR and I also don't think it works.

I think we can drop the branch, always click before waiting, and even remove the janky xpath lookup above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's been a minute since I wrote this, but I think you're right.

So let's see whether the CI workflows agree now...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re: your comment below: yeah, the timing issue is here.

I took another stab at this with less branching and less janky xpaths lookups.

@benjaminwil
benjaminwil force-pushed the product-taxon-select-component branch from 98bfa7d to f880d3d Compare October 22, 2026 22:01
@benjaminwil
benjaminwil force-pushed the product-taxon-select-component branch 2 times, most recently from 4345aad to 5695a07 Compare October 22, 2026 22:08

@jarednorman jarednorman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There's a race condition in admin/lib/solidus_admin/testing_support/feature_helpers.rb#51-58 that I think needs fixing as part of this.

@benjaminwil
benjaminwil force-pushed the product-taxon-select-component branch 2 times, most recently from d9e4f7b to e0f7d56 Compare October 23, 2026 17:20
@benjaminwil benjaminwil changed the title Create #select_taxons admin form component Create select_taxons admin form component Oct 23, 2026
@benjaminwil
benjaminwil force-pushed the product-taxon-select-component branch from e0f7d56 to 4927e78 Compare October 23, 2026 18:45
@benjaminwil

Copy link
Copy Markdown
Contributor Author

Just rebased against main to resolve conflicts after #6654 was merged.

Comment thread admin/app/components/solidus_admin/ui/forms/field/component.rb Outdated

private

def options_preloaded?(dropdown)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think this is ever returning true. Tom Select keeps the dropdown display: none until it's opened, so hidden options are never found with the default visibility and this is just burning the full wait time every time it gets called. (My testing seems to confirm this.)

I maintain that we can just always click and then do dropdown.first(".option") and avoid this complexity.

@benjaminwil benjaminwil Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

When I do that:

 -       unless options_preloaded?(dropdown)
 -         control.click
 -         dropdown.first(".option")
 -       end
 +       control.click
 +       dropdown.first(".option")

I consistently see the failures pasted below. Do you have any better ideas for how to force the wait we need?

 Failures:

  1) Product product organization adding new category creates new category and assigns it to product
     Failure/Error: expect(control).to have_text(val)
       expected to find text "Apparel" in ""
     # ./lib/solidus_admin/testing_support/feature_helpers.rb:62:in 'block in SolidusAdmin::TestingSupport::FeatureHelpers#solidus_select'
     # ./lib/solidus_admin/testing_support/feature_helpers.rb:55:in 'Array#each'
     # ./lib/solidus_admin/testing_support/feature_helpers.rb:55:in 'SolidusAdmin::TestingSupport::FeatureHelpers#solidus_select'
     # ./spec/features/product_spec.rb:235:in 'block (5 levels) in <top (required)>'
     # ./spec/features/product_spec.rb:233:in 'block (4 levels) in <top (required)>'

  2) Product product organization adding new category with invalid attributes when taxon with same name already belongs to a parent shows error
     Failure/Error: expect(control).to have_text(val)
       expected to find text "Apparel" in ""
     # ./lib/solidus_admin/testing_support/feature_helpers.rb:62:in 'block in SolidusAdmin::TestingSupport::FeatureHelpers#solidus_select'
     # ./lib/solidus_admin/testing_support/feature_helpers.rb:55:in 'Array#each'
     # ./lib/solidus_admin/testing_support/feature_helpers.rb:55:in 'SolidusAdmin::TestingSupport::FeatureHelpers#solidus_select'
     # ./spec/features/product_spec.rb:267:in 'block (7 levels) in <top (required)>'
     # ./spec/features/product_spec.rb:265:in 'block (6 levels) in <top (required)>'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The solution was to dropdown.first(".option", exact_text: /.+/)

Comment thread admin/config/routes.rb
end

resource :taxons, only: [] do
get :pretty_names

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Because no permissions include pretty_names on taxons, this will only work for super admins. Needs to auth on read, I think.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Then for now I will use the same pattern we have already committed for other solidus_admin helper controller actions (like SolidusAdmin::CountriesController#states):

skip_before_action :authorize_solidus_admin_user!

Comment thread admin/app/components/solidus_admin/ui/forms/field/component.rb Outdated
This better handles options that are loaded from a remote data source
URL.

A CI/CD timing-related failure indicated that this code was required.
We want to create a reusable taxon select component for a couple of
reasons:

1. It is too error-prone to create this by hand.
2. We want to be able to create consistent functionality where ever
   there is a taxon select required. This means always using the
   `#pretty_name` method  and having shared code to load and present a
   list of taxons.

As you can see from the diff, this commit allows us to delete some
duplicated and kinda weird code for creating bespoke taxon select
components.
The custom Solidus Select web component does not support relative URLs
as remote data sources passed to `data-src`. This is because the
underlying select library, Tom Select, only allows absolute, fully-
qualified URLs to be used as remote data sources.

Unfortunately, I have learned that our admin components do not always
have access to Rails URL helpers or default URL options before render
time. This would need to be configured per application, which isn't a
very friendly thing for a framework like Solidus to require.

But we do know that, at render time, we can get the request information
to apply implied host information to a relative URL from root. This
allows us to use path helpers component-side and still get full URLs at
render.
@benjaminwil
benjaminwil force-pushed the product-taxon-select-component branch from 4927e78 to 98aa43a Compare October 27, 2026 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Create TaxonSelect component for the new admin

3 participants