Benny Alex
Benny Alex

Reputation: 156

Avoid showing new model itself

I have got a form to create a new Model called Route. In the form is a select field, called takeover, showing all Routes and the user can select one to get an relationship to the selected Route. My problem is that the newly created Route is even selectable in the select field, because I simply return 'this.get('store').findAll('routes');'. How can I remove the new Model from the selection, because it is not possible to create a relationship to itself.

In the Route I create a empty Model and then the user can modify the attributes within the form:

//route.js
model() {
    return this.store.createRecord('route', {});
  },

Template:

//route.hbs
<form>
//some fields
//and a select-component:
{{my-select
    selected=model.takeover
    options=routes
}}
</form>

the routes which I give to the selectable options also in the route:

//route.js
 routes: Ember.computed(function () {
    return this.get('store').findAll('route');
  }).readOnly(),

So routes are all routes including the new model. But it shouldn't be able to select the model itself so I have to remove it out of routes. How can I do it?

Upvotes: 0

Views: 183

Answers (2)

Ember Freak
Ember Freak

Reputation: 12872

Try this,

routes: Ember.computed(function () {
    return this.get('store').findAll('route').then(function(result){
     return result.filterBy('isNew', false);
    });
  }).readOnly(),

Update:

If possible don't have route or routes as your route name and computed property name.

In route.js

model(){
 return Ember.RSVP.hash({
  newRecord: this.store.createRecord('route', {}),
  routes : this.get('store').findAll('route').then(function(result){
     return result.filterBy('isNew', false);
    }),
  });
},
setupController(controller,model){
 this._super(...arguments);
 controller.set('NewRecordModel',model.newRecord);
 controller.set('routes',model.routes);
}

and in route.hbs template,

{{my-select
    selected=NewRecordModel.takeover
    options=routes
}}

Upvotes: 0

sbatson5
sbatson5

Reputation: 648

You could use a computed property to simply filter by records that are not new

routes: Ember.computed.filterBy('model', 'isNew', false)

isNew is true for models that haven't been persisted yet (i.e. you have .save() it yet). You can read more about it here: http://emberjs.com/api/data/classes/DS.Model.html#property_isNew

I would keep the request to the store separate from the CP that filters the list. That way we have the logic that makes a request to our backend/store in the model hook (where it should be), then result is sent to our controller, which is where our CP for filtering can live.

Edit in response to comment:

The "Ember way"

Typically, Ember wants requests to your backend to live in the route file. It is built to have access to the store and comes equipped with async error handling. You would typically request this in your model hook:

// route.js
model() {
  return this.get('store').findAll('route');
}

If you want to create a new record here as well, you can do that like this:

// route.js
model() {
  this.get('store').createRecord('route');
  return this.get('store').findAll('route');
}

The result of the model hook is passed to the setupController method. This method is fired automatically, and it is what builds the controller object. The controller is what communicates the model to your view. This is what it does by default:

setupController(controller, model) {
  controller.set('model', model);
}

You shouldn't have to overwrite anything here, but it's good to know when the controller is created for us.

Now we can add this computed property to our controller. By default, you most likely don't have a controller.js file. You can generate one with Ember-CLI: ember g controller <route-name>

Since model was passed to our controller, we can add a computed property that filters the model:

// controller.js
routes: Ember.computed.filterBy('model', 'isNew', false)

This will be an array of all the route records that are no "new." Now our view should have access to routes.

//route.hbs
<form>
//some fields
//and a select-component:
{{my-select
    selected=model.takeover
    options=routes
}}
</form>

I'm not sure what model.takover refers to. But if you want to get the record that isNew you could similarly filter those records to return only the one that is new.

Upvotes: 1

Related Questions