ember-cli-selectize icon indicating copy to clipboard operation
ember-cli-selectize copied to clipboard

Respect optionValuePath when multiple

Open HeroicEric opened this issue 9 years ago • 9 comments

This adds support for optionValuePath when multiple: true.

Use Case

I often want to have a select that is populated with Ember Data objects but only care about selecting one of their values, such as their id. This is especially useful when using a select as a way of populating query params.

For example, imagine you have a search controller:

export default Ember.Controller.extend({
  queryParams: ['tagIds'],

  tags: [],
  tagIds: []
});

The value for tags comes from a collection of Ember Data objects set in the route:

export default Ember.Route.extend({
  setupController: function(controller, model) {
    this._super(controller, model);

    var tags = this.store.find('tag');
    set(controller, 'tags', tags);
  }
});

Your API might expect to receive an array of tag ids in the query params. To support this, you'd want to add something like the following to the search template:

{{ember-selectize selection=tagIds
  content=tags
  optionLabelPath="content.name"
  optionValuePath="content.id"}}

This could also be handled by adding an observer to set the tagIds whenever the tags array changes but that adds up really quickly when there are a lot of these on one page and, IMO is a much less elegant solution.

TL;DR;

It's confusing and limiting that setting the optionValuePath is not respected by ember-selectize. If you want to select the entire object rather than one of its properties, you can simply not specify an optionValuePath or specify 'content' as its value.

HeroicEric avatar Apr 22 '15 02:04 HeroicEric

This an interesting topic. If we take a closer look at the README, we find:

selection - Ember-selectize will set this property to the selection that was made. Usually some property on a model, for example. If multiple is true, then it should be an array.

value - Ember-selectize will set this property to the value of the selection that was made. It is not currently supported in multiple selection mode.

The idea is that selection holds the whole objects and value holds only the values according to optionValuePath. Maybe that wasn't completely clear. Also, value isn't supported in multiple mode at the moment.

#16 has some interesting research on the topic. Specifically:

After reading the docs it seems that Ember.Select provides both value and selection bindings. selection will have the selected object. value will have the selected value.

One of this project's goal is to be completely interchangeable with Ember.Select (although not necessarily in very rigid way). So, I would say that we only need to support value in multiple mode, and your problem is solved, right?

So, selecting multiple tag ids would be like:

{{ember-selectize value=tagIds
  content=tags
  multiple=true
  optionLabelPath="content.name"
  optionValuePath="content.id"}}

Selecting entire tag objects would be like:

{{ember-selectize selection=seletctedTags
  content=tags
  multiple=true
  optionLabelPath="content.name"
  optionValuePath="content.id"}}

On a separate note, we need to have optionValuePath because of the way selectize works. The addItem(value, silent) must take a unique value in (you are passing the entire object, which is ok for primitive types, but I think it can go wrong for objects when there is no optionValuePath). There might be another way to do this. But that's a different problem.

miguelcobain avatar Apr 22 '15 08:04 miguelcobain

OK, cool. I agree that it would be best to try to stay interchangeable with Ember.select.

While using value instead of selection to accomplish this is more in line with the way Ember.select currently works, it still won't make it interchangeable because Ember.select doesn't support multiple with optionValuePath and optionLabelPath. http://emberjs.jsbin.com/pifame/2/edit?html,js,console,output

So, would you still be open to a PR that adds support for multiple with value and optionValuePath and optionLabelPath?

HeroicEric avatar Apr 22 '15 16:04 HeroicEric

You mean that Ember.Select doesn't support value when multiple = true? No, it doesn't support. It is actually stated in the docs:

value String In single selection mode (when multiple is false), value can be used to get the current selection's value or set the selection by its value.

It is not currently supported in multiple selection mode.

Default: null

It wouldn't be interchangeable, yes, but what I meant from that is "someone that goes from Ember.Select to ember-selectize will get things working". In other words, every Ember.Select feature maps to ember-selectize, but not every feature of ember-selectize maps to Ember.Select. That is expected since selectize supports more features.

I would be very grateful for such a PR. :smiley:

miguelcobain avatar Apr 22 '15 16:04 miguelcobain

I would be very grateful for such a PR. :smiley:

And so would I! I have to do this all the time, and I'm always going in circles figuring out how to do it..

knownasilya avatar Jun 11 '15 16:06 knownasilya

Maybe:

{{ember-selectize content=listOfObjects
  optionValuePath='content.id'
  optionLabelPath='content.name'
  selection=listOfIds
  selectionToValues=true}}

or valueSelection=listOfIds

Either way, setting the selection or valueSelection would display the correct pre-selected content.

knownasilya avatar Jun 11 '15 16:06 knownasilya

@miguelcobain, @HeroicEric is there any other way in the existing version to get it working? looks like it could take some time for this PR to be merged.

abhilashlr avatar Jul 08 '15 06:07 abhilashlr

If you're looking for a way to have value working with multiple, you can do it with a computed property:

values: Ember.computed.mapBy('model.someArray', 'id')

where 'model.someArray' is whatever array you're binding in ember-selectize like {{ember-selectize selection=model.someArray}} (doesn't necessarily need to be within model).

So, would you still be open to a PR that adds support for multiple with value and optionValuePath and optionLabelPath?

Of course, this would be the way to go. :) I currently don't have the time needed, but I'll try to poke this if no one jumps in.

miguelcobain avatar Jul 08 '15 08:07 miguelcobain

and it will be like {{ember-selectize value=values selection=selectionModel content=contentArray}} ?

abhilashlr avatar Jul 08 '15 11:07 abhilashlr

selectionModel in your example is just a "proxy" property that the values computed property uses. So it could be named anything you want, as long as it is also in the Ember.computed dependent properties. The computed property would be placed in your controller, for example.

miguelcobain avatar Jul 08 '15 11:07 miguelcobain