Select list showing items not in model - ember.js

I have a model for my groups, which is basically the following fields:
Name
Users
I am populating a list in my template with the following
{{view "Ember.Select" content=model.users optionValuePath="content.id" optionLabelPath="content.name" attributeBindingds="size" size="5"}}
I load all users in the system in the controller, as so:
export default Ember.Controller.extend({
users: [],
init: function () {
this._super();
this.set('users', this.store.find('user'));
})
})
All users are populated as follows:
{{view "Ember.Select" content=users optionValuePath="content.id" optionLabelPath="content.name" attributeBindingds="size" size="5" }}
What is the most appropriate way of filtering the second select to contain only users that aren't in the first select - that is, to show users that do not exist in model.users

Similar to #Oren's answer, but I think you will need to declare it a property and watch the content of users via #each
users: function(){
return this.get('model.users').filter(function(user){
return !users.contains(user);
});
}.property('model.users.#each')

You can implement a filter on your controller:
users: this.get('model.users').filter(function(user){
return !users.contains(user);
});

Related

Ember - #each pass the instance of the model

For a small webapp I'm trying to do the following:
I have a list of objects (achievement-model)that's being served through a json api
Router
export default Ember.Route.extend({
model:function(){
return this.store.find('achievement');
});
});
Model
export default DS.Model.extend({
name: DS.attr('string'),
description: DS.attr('string'),
});
Template
{{#each a in model}}
<div>
<h4>{{a.name}}</h4>
<p>{{a.description}}</p>
<button {{action 'addThis'}}/>
</div>
{{/each}}
The setup of the app is that there is a list of achievements. I want one list of achievements in a database. Every user that logs in can add with the button his own achievements to his profile. If a user logs in he should see the list of all the achievements but the one he already added to his profile should have a green background color and the button removed. I know this can be done with if-statements etc.
The problem however is, how do i pass the specific model to the controller so i can log this to the userprofile? I tried the following:
<button {{action 'addThis' a}}/>
and then in the controller
actions:
addThis: function(obj){
console.log(obj);
});
which logs the object, but somehow I can't acces it to get let's say the name or id to copy it to the user-profile.
I also don't know if this is the best approach for what I'm trying to achieve?
Edit
I think this has something to do with promises. I can see the data is logged in the above console.log. I just don't know how to target it. it's wrapped in _data. I tried the afterModel to wait untill everything's loaded, but that doesn't seem to work.
What you could is to use an ItemController, e.g. which handles each item in the ArrayController,
e.g.
{{#each a in model itemController="achievement"}}
<div>
<h4>{{a.name}}</h4>
<p>{{a.description</p>
<button {{action 'addThis'}}/>
</div>
{{/each}}
Since the itemController is "achievement", by naming convention, the controller becomes
App.AchievementController = Ember.ObjectController.extend({
init: function() {
var name = this.get('name');
var description = this.get('description');
}
});

Creating a new record not pulling data from template fields

I am attempting to create a new record, however none of the data from the fields is being passed automatically, as I expected Ember to (from what I've read).
My template:
<form {{action save content on="submit"}}>
{{input value=name}}
<button type="submit"}}>Next</a>
From what I've read content is an alias for model and interchanging these makes no difference.
My route:
App.CampaignsNewRoute = Ember.Route.extend({
actions: {
save: function(campaign) {
console.log(campaign.name);
}
},
model: function(controller) {
return this.store.createRecord('campaign');
}
});
And my controller:
App.CampaignsNewController = Ember.ObjectController.extend({
pageTitle: 'New Campaign Setup'
});
When I hit 'Next' it logs undefined. Logging just the campaign shows it's an Ember model, but without the name attribute. name is defined on the campaign model. Setting the input to {{input value=content.name}} places the name attribute within the model returned, but it's still undefined. Am I missing anything in this process? The EmberJS site doesn't show how to do this, from what I can find.
--
As a side note: I was originally using App.CampaignsNewController = Ember.Controller.extend as my model was returning a hash of promises, one of which is an array and Ember didn't like me using either array or object controller. I simplified it to the above to verify it wasn't that which was causing the issue. So any solution taking this into account would be wonderful.
Edit: I can access the template fields by doing this.get('controller').get('name') but surely that is not necessary? Changing my controller to a Ember.Controller.extend also stops that from working, would love to know why. Clarification on best practice here would still be wonderful!
Edit2: this.get('controller.content').get('name') works if the controller is simply an Ember.Controller as opposed to Ember.ObjectController and the template has {{input value=content.name}}. I'll work with but hopefully someone can clarify this is the correct way.
ObjectController is the way to go here. You would have it backed by one particular model, your new model, and you would add additional properties to the controller for use in the template.
Code
App.IndexRoute = Ember.Route.extend({
actions: {
save: function(campaign) {
console.log(campaign.get('color'));
}
},
model: function() {
return Ember.RSVP.hash({
record: this.store.createRecord('color'),
all: this.store.find('color')
});
},
setupController: function(controller, model){
this._super(controller, model.record);
controller.set('allColors', model.all);
}
});
App.IndexController = Em.ObjectController.extend({
});
Template
In the template any time you want to access anything on the model backing the template, you can just access it as if the model is the current scope.
{{name}}
if you want to access any of the properties that exist on the controller you would use the property name that it is on the controller.
{{allColors.length}}
Here's an example:
<form {{action save model on="submit"}}>
Color:{{input value=color}}<br/>
<button type="submit">Next</button>
</form>
<ul>
{{#each item in allColors}}
{{#unless item.isNew}}
<li>{{item.color}}</li>
{{/unless}}
{{/each}}
</ul>
One last tip, always use getters and setters ;)
Ember Data hides the properties, they don't live right on the object, so campaign.name will return undefined forever and ever. If you do campaign.get('name') you'll get a real response.
With the example: http://emberjs.jsbin.com/OxIDiVU/792/edit

templateName as computed property

According to the documentation it is possible to specify a template for a view with templateName:
App.ShowEntryView = Ember.View.extend({
templateName: 'my-template',
});
And we can use it like:
<script type="text/x-handlebars">
<div>
{{view App.ShowEntryView}}
</div>
</script>
Could we bind the templateName to another property? Something like:
{{view App.ShowEntryView templateNameBinding="myComputedTemplateName"}}
So that in the controller we have:
myComputedTemplateName: function() {
return "this-is-my-template-name";
}.property()
The reason why I want to do this is that I have several models which I am displaying as an heterogeneous table. I want that, whenever the user selects one of the entries in the table, a detailed view is shown, using the right template according to the underlying model.
I guess you could do this:
{{view App.ShowEntryView templateName=myComputedTemplateName}}
JS Bin example

choosing a value from select

using ember.js 1.0 and ember-data 1.0 beta2
I have a model (state) with the following properties
state: DS.attr('string'),
stateName: DS.attr('string'),
and a model (customer) with the following properties
name: DS.attr('string'),
stateID: DS.attr('string'),
state: DS.belongsTo("state")
I want to be able to edit the customer and choose the state from a drop-down (that has the stateID + name showing : eg "FL - Florida" and when selected, to store the state.stateID into the customer.stateID property
this is the first time I've tried something like this , and am slightly confused about the process.
In my customer route I've set up the following:
setupController: function(controller, model) {
this._super(controller, model);
this.controllerFor('state').set('content', this.store.find('state'));
}
and my select is this:
{{view Ember.Select
contentBinding="controllers.state.content"
optionValuePath="content.stateName"
optionLabelPath="content.stateName"
valueBinding="content.stateID"
selectionBinding="content.stateID"
prompt="Select a state"
}}
now I'm confused about where to go from here.
thanks
update
changed the view to say
{{view Ember.Select
contentBinding="controllers.state.content"
optionValuePath="content.stateID"
optionLabelPath="content.stateName"
valueBinding="customer.stateID"
}}
and I still don't get the stateid property to change . I've also tried
selectionBinding="customer"
to no avail.
update #2
I suspect that my problem may be linked to the property name. I changed the customer.stateID property to be customer.foobar and changed the select to read
{{view Ember.Select
contentBinding="controllers.state.content"
optionValuePath="content.stateName"
optionLabelPath="content.stateName"
valueBinding="foobar"
class="form-control"
}}
and now customer.foobar is updated with the value from the select.
Is there a problem with a property called stateID on customer ? I have a state model and state controller etc so is there a conflict ?
after all that - the problem was in the models themselves. The state model does not have a stateID field, it's state.state ...
My heartfelt apologies to all that wasted their time on this. Such a stupid error.
Okay, maybe not the best solution, but it works well:
App.ItemModalController = Ember.ObjectController.extend({
content: [],
availableCategories: function() {
return this.store.find('category');
}.property(),
//...
});
And the select:
{{view Ember.Select
contentBinding="availableCategories"
valueBinding="categorySelected"
optionLabelPath="content.title"
optionValuePath="content.id"
prompt="Please select a category"
class="form-control"
}}

Ember: How to set controller model for use in select view

See: http://jsfiddle.net/cyclomarc/VXT53/8/
I have a select view in which I simply want to list all the authors available in the fixtures data. I therefore try to use a separate controller in which I want to set the content = App.Author.find(), but that doesn't work ...
App.AuthorsController = Ember.ArrayController.extend({
//content: App.Store.findAll(App.Author)
//content: App.Author.find()
});
I then want to use the AuthorController for contentBinding in the selectView, but also this is not succsesful ...
{{view Ember.Select
contentBinding="App.AuthorsController"
optionValuePath="content.id"
optionLabelPath="content.name"
valueBinding="App.PublicationsEditController.author"
prompt="Select an author"
}}
The use case is that I have a publication in which an author is set (e.g. Marc) and I want to allow the user to change this to one of the available authors and then bind the new selected author to the publication model so that after a save the new author is saved.
I guess this what you are after: http://jsfiddle.net/VXT53/10/
I had to do a couple of changes, first your router map where slightly wrong, the edit segment had to go after the id to match your template name pulications/edit:
App.Router.map(function () {
this.resource('publications', { path: '/' }, function () {
this.route("edit", { path: "/edit/:publication_id" });
});
});
Your Ember.Select where binding to a class instead to some content, to set it up correctly I've defined a PublicationsEditControllet to requiere trough the needs API access to the AuthorsController's content:
App.PublicationsEditController = Ember.ObjectController.extend({
needs: ['authors'],
...
});
this is how you then use it for your select:
{{view Ember.Select
contentBinding="controllers.authors.content"
optionValuePath="content.id"
optionLabelPath="content.name"
valueBinding="content.name"
selectionBinding="selectedAuthor"
prompt="Select an author"
}}
Furthermore I've created a setupController hook which is used to set the AuthorsController's content to the list of authors:
App.PublicationsRoute = Ember.Route.extend({
model: function () {
return App.Publication.find();
},
setupController: function(controller, model) {
this._super(controller, model);
this.controllerFor('authors').set('content', App.Author.find());
}
});
And lastly on you PublicationsEditController is a new property attached selectedAuthor to hold the currently selected author for binding etc.
App.PublicationsEditController = Ember.ArrayController.extend({
needs: ['authors'],
selectedAuthor: null
});
I guess this should work now and brings you one step further.
Hope it helps.