13
votes

I am trying to do something pretty basic with Ember and Ember Data.

1) Posts belongsTo Users; Users hasMany Posts

2) In the create new Post form, I want to have a select/dropdown of all Users

3) When I edit a post (using the same form), I want to bind it correctly back to the dropbox

Question: What is the best practice to do the dropdown that binds to the list of users? How can I bind the edit form to populate the dropdown again?

User Model:

App.User = DS.Model.extend({
  posts: DS.hasMany('post', {async: true}),
});

Post Model:

App.Post = DS.Model.extend(Ember.Validations.Mixin, {
  user: DS.belongsTo('user', {async: true}),
});

Create New Post Form:

{{view Em.Select
  content=users <<<<< How do I bind this.store.find("user") here?
  optionValuePath='content.id'
  optionLabelPath='content.name'
}}

I don't understand the best practice to bind the select content with users.

Attempt 1:

*I am using Ember-Form

  {{em-select
    property="user_id"
    label="user"
    prompt="Select user:"
    content=controllers.users.content
    optionValuePath="content.id"
    optionLabelPath="content.first_name"
  }}

And on the save action:

newItem.set('user', this.store.getById('user', this.get('user_id')));

I tried to use user_id as my property for the form, and translate back to a user object to assign to the post when I save. However, this method is kind of stupid because I am actively translating user_id to user object every time I save. I feel like there should be a way that that is done automatically if I did the correct binding, instead of jumping through hoops to bind the property as user_id. This also makes it hard for me to bind back when I use the same form for editing the post. Since all the relationship has been setup, I have a feeling that I am doing something wrong here. I think there must be a better way.

Thanks!

4

4 Answers

7
votes

As of September 2014 there is an issue with Ember.Select plus { async: true }. They don't play well together.

myModel.get('myAsyncRel') will return a promise, Ember.Select is not promise aware, so it cannot handle this properly.

One workaround is to use a non-async relationship.

Another workaround is to use something like this:

2
votes

The ember team has opened an issue (#5259) for this problem, they are planning to rewrite the whole Ember.Select part.

In the meantime you can use this Add-on from thefrontside:

{{#x-select value=bob action="selectPerson"}}
  {{#x-option value=fred}}Fred Flintstone{{/x-option}}
  {{#x-option value=bob}}Bob Newhart{{/x-option}}
{{/x-select}}

Install it with ember install emberx-select


EDIT As Stefan Penner wrote, you can now use the ember select as follows (jsbin):

<select onchange={{action "changed" value="target.value"}}>
    {{#each model.choices key="@identity" as |choice|}}
      <option value={{choice}} selected={{is-equal currentValue choice}}>{{choice}}</option>
    {{/each}}
</select>  
0
votes

When you say dropdown I presume you mean a select box? Ember's API has a select view that handles all of the data binding. Here are the docs for Ember.Select.

You can use it in your post form like so:

{{view Em.Select
  content=users
  selection=user
  optionValuePath='content.id'
  optionLabelPath='content.name'
}}

If you're using Dockyard's awesome ember-easyForm library you can utilize an Em.Select like this:

{{input user type='as'
  collection='users'
  selection='user'
  optionValuePath='content.id'
  optionLabelPath='content.name'
  prompt='Choose type...'
}}

Advanced UI using Chosen can be easily integrated with Ember like this.

0
votes

New deprecation information was added in Ember 1.13 for Ember Select, see http://emberjs.com/deprecations/v1.x/#toc_ember-select.

The new recommended approach in Ember 1.13/2.0 is to implement a component yourself:

e.g. /components/my-select.hbs

<select>
  {{#each users "id" as |user|}}
  {{log address}}
    <option value="{{user.id}}">
      user.name
    </option>
  {{/each}}
</select>

The ember link shows how to implement selection with selected={{is-equal item selectedValue}} and creation of a is-equal helper.