Product Configurator Nested Lists

I'm evaluating Retool for use within the business, and I've chosen to take a look at one of my ongoing projects in PowerApps as a possible project.

We have a number of complex products for which we have existing configurators implemented in Excel/Access/whatever, and we're looking at replacing all of these with a single system with version control etc. These configurators could have over one hundred choices, and I would therefore like to drive this from data, rather than dropping hundreds of combo boxes onto the form.

As you'd expect, some choices affect other choices, so that the entries in each combo box should be filtered depending on previous choices, or marked as invalid when changes are made to previous selections. Obviously it's also necessary to be able to save configuration and to reload saved configurations for editing.

As part of a similar evaluation, this has been prototyped in PowerApps, where the configurator itself, including the validation data, is contained in a single Sharepoint list. This performs about as well as you'd expec, but is copied to a local collection for use.

The configurator with Demo selections looks like this:

This is done in PowerApps with a gallery control inside a gallery control. The outer gallery is populated with distinct categories from the sharepoint list, inner galleries are populated with specification names where the category equals the category for the outer item, and so on. PowerApps allows you to reference the entries for each item in the gallery and use that within the query, either by the name of the control within the gallery, or by using ThisItem.

All aspects of this are working in PowerApps, but the performance is not ideal, and the backend options for PowerApps are not ideal for us either.

What I'm struggling to understand is how this can be done in Retool. I can use nested lists in Retool as a basis for this, but it appears that I need to provide a complete dataset with all data pre-filtered and ready to display, and that I can't refer to the records inside the outer list to filter data further in.

Am I misunderstanding something here, or going about it in the wrong way? I'm not fussy about the controls used to achieve the effect, but the UI needs to be driven by the data, so other options might need to add controls on the fly according to the data. I realise that doing away with the category headings would simplify matters, but it's a long list without them, and not ideal.

Thanks in advance for any advice.

Andrew

In retool I have put this together:

The inner and outer lists are driven by a JS query and the inner list select label is driven like this:

{{ ProdSpecNest2.data[ri[0]].specificationname[ri[1]] }}

But to populate the select, and to load the selected setting into the select I think I need to query data based on the above value of the label, setting the Data Source and Value of the select.

So let's say I select Animal type as Dog
then breeds should be list of dog breeds.
Essentially, you would use an event handler On Click in the Inspect panel for the Animal Type field that would trigger your query that gets Breeds where animal_type = {{animal_type_comonent_name.value}}
If I am following you correctly....
There are numerous ways in which you can build the app and run operations using event handlers, temp states, query JSON with SQL, etc.. I would speak with Retool team directly and ask them to run through your scenario and assess more in depth. I will say that based on my experience in working with a pet company in the past and building an internal customer service tool, Retool was chosen for its capabilities that are easy to wrap your head around and get to an MVP very fast and then scale from there. Just my $.02.

1 Like

Thanks Scott, I appreciate the confirmation that this looks viable, the actual validation in the other version works by marking each item in the collection, if an item has no dependencies, then enable it. If all dependencies are met, then enable it. If not all dependencies are met then disable it. The whole list is marked, then the presentation layer takes care of putting all the items in the right place.

Most items are not dependent on anything, but some have multiple dependencies. Sometimes there are a few different options for the dependencies. I don't think that would be particularly unusual for a configurator though.

The animals example has been used to make it easy to understand what the dependencies should be. Even within the company the actual product dependencies are not so obvious.

No animals were configured in the making of this example.

1 Like

Hey @AndrewH!

This is a really interesting question, where is the logic for your form currently stored? Is it possible to describe it in a JSON or similar format or are you needing to build it out manually in each type of software you've used so far?

Hi @Kabirdas, In Power Apps, the outer list is populated directly from the query - Distinct(colProdSpecData,Title) which pulls the distinct titles from the in memory collection colProdSpecData.

The inner list is populated from the same collection. Each section queries against the out section it's nested in: Distinct(Filter(colProdSpecData,Title = CategoryLabel.Text),SpecificationName)

So using the category label (Accessories, Animal Type, Characteristics) to drive the specification name label (Accessories, Animal Type, Breed, Legs)

The combo box does the same, but filtering on the specification name: Filter(colProdSpecData,SpecificationName = ThisItem.SpecificationName And Enabled = 1)

When selections are made, items are marked as enabled or disabled in colProdSpecData by checking if all of their dependencies are in the collection of selected items. Only enabled items are displayed.

Selections are marked as invalid higher up the list if the selected item doesn't exist in the enabled items by setting the colour.

Power Apps doesn't do a bad job with the nested galleries, but is rather sluggish on data access. I've glossed over some of the hoops I've needed to jump through to get this to work.

I'm sure that I need to rethink this with a Retool mindset to stop it getting silly. I don't think it's such an unusual use case, but it's not the easiest example to start with in a new platform!

I see, thanks for that additional context! A couple more questions:

  • Would user selections ever change the specification name labels? Or is it just the options in each that change?
  • When you check the dependencies is it assumed that each selection is unique or does it need to be tied to the field it was selected from? In other words, are you checking against an object that looks more like ["Cat", "Persian", "4", "Cat Collar"] or {type: "Cat", breed: "Persian", legs: 4, accessories: "Cat Color"}?

This is my first time seeing this particular use case, but I can certainly see it being a common one. Coincidentally, another user recently asked a similar question here, but I think there may be a few different ways to approach this.

Ideally, if the selections were empty, then the specification would not appear, and if there were only one choice, then the choice would be selected automatically.

The Power Apps version uses an ID field to drive further selections which suits the collection model used there, but the JSON equivalent would need to use your second version: {type: "Cat", breed: "Persian", legs: 4, accessories: "Cat Color"}. Values like "4" take their meaning from the context in particular. 4 legs is not the same as 4 horns, in this increasingly strained animal example.

We would expect to be driving the dependencies from more than one field to prevent incorrect option from being available. {legs: "4"} is not as precise as {type: "Cat", breed: "persian", legs: "4"} for cases where this matters.

I'll take a good look at the linked example, it all helps to understand what's going on.

Hey @AndrewH!

Just want to add a more complex version of the example given above to illustrate some of what might be possible in Retool. Again, there isn't a built-in way to generate a component that does exactly what you're looking for but, having done some experimenting, it seems there are certainly a few different approaches you might take. The following is just a start, but might give you some ideas as to what kind of customization is possible.

It uses a schema for each category that takes advantage looks something like the following:

{
    label: "Characteristics",
    dependencies: {
      breed: ["."],
    },
    specifications: [
      {
        label: "Legs",
        id: "legs",
        selections: [
          {
            value: 2,
            dependencies: {
              animal_type: ["Bird"],
            },
          },
          {
            value: 4,
            dependencies: {
              animal_type: ["Cat"],
            },
          },
        ],
      },
      {
        label: "Color",
        id: "color",
        selections: [
          {
            value: "Brown",
            dependencies: {
              animal_type: ["Cat"],
            },
          },
          {
            value: "Black",
            dependencies: {
              animal_type: ["Cat"],
            },
          },
        ],
      },
    ],
  },

Dependencies are arrays of strings to be matched on to check whether or not the user has selected the necessary values to enable either a category or particular option in a specification. The matching is done using some preloaded JavaScript:

window.checkDependencies = (dependencies, user_selections = {}) => {
  for(let key in dependencies){
    if(!dependencies[key].some(value => user_selections[key]?.match(value))){
      return false;
    } 
  }
  return true;
}

Throughout, nested listview syntax is used to access different parts of the schema. The user selections themselves are stored in a temp state, so each select has a form data key pulled from the underlying schema:

and an event handler to store the data:

Then the visibility of certain options is done by checking the option's dependencies against the user selection:

Something similar is done for the labels/listviews that comprise each category:

Feel free to play around with it yourself using the attached JSON! Hopefully, it gives you some ideas to try that fit your specific case a bit better :slightly_smiling_face:
dynamic_listview_selects (3).json

1 Like