Search code examples
ember.jshtml-selectdropdownboxcascadingdropdown

Get the value of another select control in Ember


My situation is I have a table where the user can add suppliers, and edit any existing ones (so there are potentially multiple records). Three of the fields (Type, Name, Version) come from a lookup object returned by the API (which is one table in the backend database).

Before clicking 'edit' Before clicking edit

In edit mode In edit mode for a single row

The thing is, I need these select elements to be "chained" (or cascading), but since they're populated from the same object, it's more like the selection of "Type" will filter the options available for "Name" and likewise selecting Name will further restrict the options available for Version.

However, since this is just one record being edited, these selects are in an {{#each supplier in suppliers}} block to generate the rows, and show selects if that record's isEditing property is true, so the value or selection is the per-record value, e.g. supplier.type and not a single property on the whole controller.

I've tried to come up with multiple ways to do this, but so far haven't found a solution to cascading dropdowns with multiple records since that means the value of any one select is dependent on the record.

I think I could get the option filtering to work if I knew how to reference the value of say the Type dropdown from within the controller, but then again it's conceivable that two records could be in edit mode at once, so modifying any property on the controller to populate the selects would affect the others too, and that's not good. I just really wanted to figure this out so I didn't have to pop up a modal dialog to edit the record.


Solution

  • You should use components to handle each row seperately.

    Let's say that you have something like this:

    {{#each suppliers as |supplier|}}
      // .. a lot of if's, selects and others
    {{/each}}
    

    If you find yourself using {{#each}} helper and your block passed to that helper is more than one line, than it's a good sign you probably need a component there.

    If you create a component named, let's say, SupplierRow you could make it as follow:

    module export Ember.Component({
      editing: Ember.computed.alias('model.isEditing'),
      types: Ember.computed('passedTypes', function() {
        // .. return types array for that exact supplier 
      }),
      names: Ember.computed('passedNames', 'model.type', function() {
        // .. return names array for that exact supplier based on possibleNames and model.type
      }),
      versions: Ember.computed('passedVersions', 'model.type', 'model.name', function() {
        // .. return versions array for that exact supplier based on possibleVersions and model.type and model.name
      }),
      actions: {
        saveClicked() {
          this.sendAction('save', this.get('model'));
        }
      }
    });
    

    The template would basically look similiary to what you have currently in your {{#each}} helper. It would be rendered something like this:

    {{#each suppliers as |supplier|}}
      {{supplier-row model=supplier possibleTypes=types possibleNames=names possibleVersions=versions save="save"}}
    {{/each}}