Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-Select with hasMany attribute error #105

Open
abobwhite opened this issue Jun 21, 2015 · 11 comments
Open

Multi-Select with hasMany attribute error #105

abobwhite opened this issue Jun 21, 2015 · 11 comments

Comments

@abobwhite
Copy link

The error Uncaught Error: Cannot set read-only property "<propertyName>" on object is thrown by Ember when selecting items from the available options using ember-select-2 when selection is set to a an attribute on a model that is defined as a hasMany attribute.

Here is a SO article that appears relevant: http://stackoverflow.com/questions/24184706/ember-data-createrecord-with-hasmany-relationship-without-saving

And a closed Ember Data issue that seems relevant as well: emberjs/data#2233

I switched to ember-select-2 after a couple years of rolling my own solution pre-ember-cli. I decided to go with this component due to its simplicity and to simplify my components. I thought this would just work but it appears to have at least 1 issue for a very common use-case.

@syedimty
Copy link

I am also facing the same issue. @abobwhite Have you found any solution ?

@abobwhite
Copy link
Author

I thought about creating a pull request but I do not know how to test local changes with ember addon. What I did instead was to manually create an array which contains ids for the selection property and added an observer to listen for changes on that array to push/remove objects from the hasMany itself. It was actually a pain in the butt .... but it worked. I would love to get the real fix into this addon, though.

@syedimty
Copy link

@abobwhite Even i was thinking of the same approach. Even though is not a clean solution, glad that it worked. Will be doing the same i guess.

@alexlafroscia
Copy link

I'm having the same issue. I'll fork the repo and look into fixing this.

@alexlafroscia
Copy link

Took a look, it would require changing the architecture of the plugin quite a bit. If you checkout this line here, .set is called on the value property, which in our case is a relationship. Since you can't call .set on a relationship, this is where the error happens.

Fixing it would mean tracking the before/after state of each change, detecting what was added or removed, and then performing the right action on each item.

@adamlc
Copy link

adamlc commented Aug 27, 2015

Any thoughts on this @iStefo? After switching to this plugin I've just come across this and it seems like it'd be a pretty common use case 👍

@alexlafroscia
Copy link

@adamlc I've just switched to ember-cli-selectize, which supports relationships out of the box.

@angouleme
Copy link

For everyone experiencing issue with hasMany and select2, I have a workaround that worked very well for me. Let's say we have post that can have many tags, and we use select2 to choose tags from list. We will need custom component that extends select2 (for instance tags-search) in which we'll override didSelect method, and computed property in post model, that will return array of tags' names. Final code can look a bit like this:
In template:

tags-search [
  content=tags 
  value=model.tagsList
  multiple=true
  model=model ]

instead of content you can use query, it won't change the outcome. For displayed value in select box we're using computed property that returns list of tag names (at the bottom of post). Model (in this case post) must be passed to component - its tags property will be set to whatever was selected.

Search-tags component:

import Select2Component from "your-app-name/components/select-2";

export default Select2Component.extend({
  didSelect(values, component) {
    var post = component.get("model");
    post.set("tags", values);
    return;
  }
})

Computed property in post model:

  tagsList: Ember.computed("tags", function() {
   var list = [];
   this.get("tags").forEach(function(tag) {
     var tagName=tag.get("name");
     list.push(tagName);
   })
   return list; 
 })

Hope this helps :)

@richmolj
Copy link

Very similar to @angouleme's solution, here's a util that removes the need for a custom component. This will keep your hasMany in sync with select2 via computed property get/set:

Usage:

# on Post
tagSelects: selectableChildren('tags')

# on Tag
asSelection: ->
  name: @get('name'), id: @get('id')
<select-2 value=model.tagSelects...

The util:

selectableChildren = (associationName) ->
  Ember.computed "#{associationName}.@each",
    get: (key) ->
      @get(associationName).map (assn) -> assn.asSelection()

    set: (key, selections) ->
      @set(associationName, [])
      for selection in selections
        child = @store.createRecord(@relationshipFor(associationName).type, selection)
        @get(associationName).addObject(child)
      @get(key)

`export default selectableChildren`

@abobwhite
Copy link
Author

I think we're all covered with the alternative solutions but the main thing here is that Ember Data is a core component of the Ember world and if this addon is to be taken seriously and used by more people, this support just needs to be added so we don't need lengthy workarounds

@smk1992
Copy link

smk1992 commented Aug 19, 2016

any updates on this?

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

No branches or pull requests

7 participants