Set default value for Ember Select - ember.js

This fiddle requires user to select option B , so it gives that message when other than B option is selected. Still, I need to set default option as B in select dropdown.
http://jsfiddle.net/fortm/YpEMH/
I tried this but seems not working for setting selectedName in SearchController ..
selectedName = this.get('model').objectAt('firstChild')

You can set the selectedName controller property in the route's setupController hook:
setupController: function(controller, model) {
controller.set('model', model);
controller.set('selectedName', model.findProperty('firstName', 'B'));
}
That way when the route is rendered, the select will default to "B".
I updated the fiddle.

Ember select now allows you to set a default value based on a controller property. See http://emberjs.com/api/classes/Ember.Select.html for more details but here is a summary:
App.TreesIndexController = Ember.ArrayController.extend({
defaultTree: 'enzyme',
treeTypes: ['enzyme', 'chembl']
});
{{view Ember.Select
content=treeTypes
prompt="Please select a target class"
value=defaultTree}}
The option select would default to 'enzyme' in this example.

Related

Ember Route Query Params

i would like to open a new perspective with query params.
That means in my index.hbs i click a button get the value from the input field.
After that i will open a new route in my case map-view with path '/map' with query params like
localhost:4200/map/?search=xyz
when i do in my index controller:
queryparams:['location'],
location:null,
and in my route
actions:{
search(location){
this.transitionTo('map-view');
}
}
i get on my index url instantly
/?location=xcyxyx
but i want on my map route
localhost:4200/map/?search=xyz
Define search property in index.js controller, use it for queryParams value transitioning to map-view route.
index.hbs
{{input value=search}}
<br />
<button {{action 'transitionToLocation'}}> Search</button>
controllers/index.js - refer transitionToRoute
import Ember from 'ember';
export default Ember.Controller.extend({
search:'india',
actions:{
transitionToLocation(){
this.transitionToRoute('map-view',{queryParams: {search: this.get('search')}});
}
}
});
routes/map-view.js
Define queryParams search with refreshModel true then this will force to fire beforeModel and model and afterModel hook for search property change.
import Ember from 'ember';
export default Ember.Route.extend({
queryParams:{search: {refreshModel:true}},
});
The queryparam is going to be 'search' since that is what you want showing in your URL.
The syntax can be found on:
https://guides.emberjs.com/v2.10.0/routing/query-params/
Further down on that page, it shows how to specify query parameters when using transitionTo. Hope this helps.

How to render a view in a nested route from an Ember select

I'm trying to accomplish a simple behavior:
Take an ember select view populated by its corresponding controller's model, bind an action that takes the id of that item and either renders or redirects to that view's outlet
I have ember select and bindings setup but how to actually render/translate that model into to the outlet has been evasive.
I have a jsbin: http://jsbin.com/nidi/2/edit?html,js,output
Any help would be greatly appreciated
I think you had your transition defined incorrectly, it should have been
App.MoviesController = Ember.Controller.extend({
movieSelected: function(){
var selectedMovie = this.get('selectedMovie');
this.transitionToRoute('movie',selectedMovie);
}.observes('selectedMovie')
});
Updated link http://jsbin.com/moki/1/edit?html,js,output
Actually, you just forgot to pass model in you transitionTo call, here is your updated link instead http://jsbin.com/nidi/2/edit?html,js,output

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.

Ember, Ember-data, and jquery-ui.dialog, "Oh my!"

The task:
Open a form in a lightbox to create a new "event"; the opened form should be bookmarkable.
The road blocks:
There are examples of opening a lightbox using {{action}} tags, but could not find one that opened in its own route.
There are many examples using older versions of ember.js.
There is not a lot of documentation related to ember-data and REST (I know, I know...it isn't "production ready").
The problem:
The fields in the form were not being tied to a backing model so "null" was being posted to my servlet (a Spring controller).
My very first iteration was not too far off from the final outcome (jsfiddle). The thing that finally made it works swapping this:
EP.EventsNewRoute = Ember.Route.extend({
...
setupController : function(controller, model) {
controller.set("model", model);
},
...
});
...for this:
EP.EventsNewRoute = Ember.Route.extend({
...
setupController : function(controller, model) {
this.controllerFor("events-new").set("model", model);
},
...
});
The question:
Why does the setupController function need to call controllerFor in order to properly set up the model?
And finally, since I struggled to find a fully-functional example, I wanted to make this accessible (and hopefully discover improvements).
Here's the fiddle: http://jsfiddle.net/6thJ4/1/
Here are a few snippets.
HTML:
<script type="text/x-handlebars">
<div>
<ul>
{{#linkTo "events.new" tagName="li"}}
Add Event
{{/linkTo}}
</ul>
</div>
{{outlet events-new}}
</script>
<script type="text/x-handlebars" data-template-name="events-new">
<form>
<div>
<label>Event Name:</label>
{{view Ember.TextField valueBinding="name"}}
</div>
<div>
<label>Host Name:</label>
{{view Ember.TextField valueBinding="hostName"}}
</div>
</form>
</script>
JavaScript:
...
EP.Router.map(function() {
this.resource("events", function() {
this.route("new");
});
});
EP.EventsNewRoute = Ember.Route.extend({
model : function() {
return EP.Event.createRecord();
},
setupController : function(controller, model) {
//controller.set("model", model); // Doesn't work? Why not?
this.controllerFor("events-new").set("model", model); // What does this do differently?
},
...
});
EP.EventsNewController = Ember.ObjectController.extend({
save : function() {
this.get("content.transaction").commit(); // "content.store" would commit _everything modified_, we only have one element changed, so only "content.transaction" is necessary.
}
});
EP.EventsNewView = Ember.View.extend({
...
});
EP.Event = DS.Model.extend({
name : DS.attr("string"),
hostName : DS.attr("string")
});
Resources:
http://emberjs.com/guides/routing/setting-up-a-controller/
http://emberjs.com/guides/getting-started/toggle-all-todos/ (trying to mimic what I learned, but morph the add-new to a new route)
Writing a LightboxView causes problems / Integrating DOM Manipulating jQuery-Plugins makes actions unusable (lightbox "example")
Dependable views in Ember (another lightbox "example" but doesn't have routes for the lightbox opening)
Why does the setupController function need to call controllerFor in order to properly set up the model?
Ember makes URLs a very integral part of its conventions. This means that the state of your application is represented by the route it is on. You've grokked most of this correctly. But there are couple of subtle nuances, that I will clarify below.
First consider an app with the following URLs,
/posts - shows a list of blog posts.
/posts/1 - shows a single blog post.
And say clicking on a post in the list at /posts takes you to /posts/1.
Given this scenario, there 2 ways a user will get to see the post at /posts/1.
By going to /posts and clicking on the 1st post.
By typing in /posts/1, via bookmarks etc.
In both these cases, the PostRoute for /posts/1 will need the model corresponding to Post id 1.
Consider the direct typing scenario first. To provide a way to lookup the id=1 post model, you would use,
model: function(params) {
return App.Post.find(params.post_id);
}
Your template for post will get the model and it can render using it's properties.
Now consider the second scenario. Clicking on post with id=1 takes you to /posts/1. To do this your template would use linkTo like this.
{{#linkTo 'post' post}} {{post.title}} {{/linkTo}}
Here you are passing in the post model to the linkTo helper. It then serializes the data for the post into a URL, ie:- '/posts/1'. When you click on this link Ember realizes that it needs to render the PostRoute but it already has the post model. So it skips the model hook and directly calls setupController.
The default setupController is setup to simply assign the model on the controller. It's implemented to do something like,
setupController: function(controller, model) {
controller.set('model', model);
}
If you do not need to set custom properties on your controller, you don't need to override it. Note: if you are augmenting it with additional properties you still need to call _super to ensure that the default setupController behaviour executes.
setupController: function(controller, model) {
this._super.apply(this, arguments);
controller.set('customProp', 'foo');
}
One final caveat, If you are using linkTo and the route does not have dynamic segments, then the model hook is still called. This exception makes sense if you consider that you were linking to the /posts route. Then the model hook has to fire else Ember has no data to display the route.
Which brings us to the crux of your question. Nearly there, I promise!
In your example you are using linkTo to get to the EventsNewRoute. Further your EventsNewRoute does not have dynamic segments so Ember does call the model hook. And controller.set("model", model); does work in so much as setting the model on the controller.
The issue is to do with your use of renderTemplate. When you use render or {{render}} helper inside a template, you are effectively getting a different controller to the one you are using. This controller is different from the one you set the model on, hence the bug.
A workaround is to pass the controller in the options, which is why renderTemplate gets this controller as an argument.
renderTemplate: function(controller) {
this.render("events-new", {
outlet : "events-new", controller: controller
});
}
Here's an updated jsfiddle.
Final Note: Unrelated to this question, you are getting the warning,
WARNING: The immediate parent route ('application') did not render into the main outlet and the default 'into' option ('events') may not be expected
For that you need to read this answer. Warning, it's another wall of text! :)

Selected select on default ember js

I have a model Currencies. Fields in the model are name:string and default:boolean.
On the backend only one of records in database can have default:true. I want it to be selected by default in select in Ember js.
Please give me an example how to make such select and use it
Example:
name: type1 default: false
name: type2 default: true
name: type3 default: false
I want to generate such select :
<selected>
<option>type1</option
<option selected=selected>type2</option
<option>type3</option
</selected>
Route.js
#route 'addincome', { path: 'operations/addincome' }
EmberMoney.AddincomeRoute = Ember.Route.extend
model: ->
EmberMoney.IncomeOperation.createRecord()
setupController: (controller, model) ->
controller.set('currencies', EmberMoney.Currency.find())
controller.set('content', model)
addincome.handlebars
// Some output with Incomes records
{{view EmberMoney.Select viewName="select"
contentBinding="controller.currencies"
optionLabelPath="content.name"
optionValuePath="content.id"
selectionBinding="controller.defaultType"}}
addincome_controller.js
EmberMoney.AddincomeController = Ember.ObjectController.extend({
setDefaultCurrency: function(){
if(this.get('currencies.isLoaded')){
this.set('defaultType', this.get('currencies').findProperty('default'));
}
}.observes('currencies.isLoaded')
})
My answer builds upon that one already posted. The answer is to use the selectionBinding and a clever way to set it up:
{{view Ember.Select
contentBinding="controller.types"
optionLabelPath="content.name"
optionValuePath="content.id"
selectionBinding="controller.selectedCurrency"
}}
EmberMoney.IncomesController = Ember.ArrayController.extend({
selectedCurrency : null,
currenciesObserver: function(){
var currencies = this.get("currencies");
var default = currencies.findProperty("default");
if(default)
this.set("selectedCurrency", default);
}.observes('currencies.#each')
});
How does the solution work?
We set up a selectionBinding (two way) between the Select control and your controller. If you set a currency in your controller in the property 'selectedCurrency', it will be the selected value in the Select control. Vice versa if you select a currency in the Select Box, it will be set in your controller.
I am doing the initial setup with the helper of an observer. The observer is called each time the watched currencies array changes.
Every time it is called, it tries to find a default currency. If it finds one, it sets it in your selectedCurrency property. Now the selectionBinding kicks and does its magic for you.
An additional advantage of this solution is, that you can grab the selected value easily from the property, if the user chooses another currency.
Use selectionBinding for the selection, and ComputedProperty to find the appropriate item
Update
EmberMoney.AddincomeController = Ember.ObjectController.extend({
setDefaultCurrency: function(){
if(this.get('currencies.isLoaded')){
this.set('defaultType', this.get('currencies').findProperty('default'));
}
}.observes('currencies.isLoaded')
})
The advantage of using isLoaded over #each for the observer is that the observer wont get fired everytime a currency is added instead it makes sure to set the value once the entire collection is loaded, Again it is upto the use case to determine which to use when
Details about findProperty
Hope this helps
Screenshot