Handling multiple checkbox array in Ember.js - ember.js

Here is the thing I have a form which have multiple checkboxes and they have the same name attribute "classifications[]"
with the code:
<input type="checkbox" name="classification[]" value="Value 1" />
<input type="checkbox" name="classification[]" value="Value 2" />
<input type="checkbox" name="classification[]" value="Value 3" />
this works properly by default it posts "classification[]" like this
[ 0 => "Value 1", 1 => "Value 2"]
but I want this to work in an ember app so I did this (shortened version)
// index.html
{{input type="checkbox" name="classification[]" value="Cell Member" checked=classification}}
App.ApplicationController = Ember.Controller.extend({
var user = this.store.createRecord('user',{
classification: this.get("classification")
})
user.save();
})
App.User = DS.Model.extend({
classification: DS.attr("string")
});
but the only posted classification value is True..

try this
// index.html
{{#for possibleValues}}
<label>{{this.label}}</label>
{{input type="checkbox" value=this.isChecked}}
{{/for}}
<a {{action save}}>save</a>
var possibleValue = [{
label: 'Label for value 1',
isChecked: false,
value: 'Value 1'
},{
label: 'Label for value 2',
isChecked: false,
value: 'Value 2'
},{
label: 'Label for value 3',
isChecked: false,
value: 'Value 3'
}];
App = Ember.Application.create();
App.ApplicationAdapter = DS.RESTAdapter.extend();
App.ApplicationController = Ember.ObjectController.extend({
init: function () {
this._super();
var user = this.store.createRecord('user');
this.set('content', user);
},
actions:{
save: function () {
var user = this.get('content'),
collected = user.get('classifications');
this.set('collected', collected);
user.save();
}
},
//executes when isChecked is changed in one item of possibleValues
collectChecked: function () {
var classifications;
classifications = this.get('possibleValues').filterBy('isChecked', true); //filter checked only
classifications = classifications.mapBy('value'); //map values
this.set('classifications', classifications);
console.log(classifications);
}.observes('possibleValues.#each.isChecked'),
possibleValues: possibleValues
});
App.RawTransform = DS.Transform.extend({
deserialize: function(serialized) {
return serialized;
},
serialize: function(deserialized) {
return deserialized;
}
});
App.User = DS.Model.extend({
classifications: DS.attr('raw')
});
http://jsbin.com/dokiwati/6/edit

Related

Power-select not showing the selected value

My power-select will not display the selected value.
I have three power-selects in this component and two are working fine, but the third (companyType) is acting strangely - the value is blank when you first go to the form. When you select a value it sticks for that record from then on (until you refresh the page)
Template:
// templates/components/companies/edit-new-form.hbs
{{#bs-form formLayout=formLayout model=company onSubmit=(action "save") as |form|}}
<label>State:
{{#power-select
selected=company.state
options=states
onchange=(action "chooseState")
as |name|
}}
{{name}}
{{/power-select}}
</label>
<label>County:
{{#power-select
selected=company.county
options=countyNames
onchange=(action "chooseCounty")
as |name|
}}
{{name}}
{{/power-select}}
</label>
<label>Company Type:
{{#power-select class="select"
selected=company.companyType
options=companyTypes
onchange=(action "chooseCompanyType")
as |name|
}}
{{name.companyType}}
{{/power-select}}
</label>
{{/bs-form}}
JS:
// componnents/companies/edit-new-form.js
export default Ember.Component.extend({
company: null,
router: Ember.inject.service('-routing'),
ajax: Ember.inject.service(),
store: Ember.inject.service(),
countyNames: Ember.computed('company.state', function() {
return this.get('ajax').request(config.host + '/api/counties/' + this.company.get('state')).then( (json) => json.map( (county) => {
return county.countyName;
})
)
}),
states: ['AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MI', 'MN', 'MO', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM', 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VT', 'WA', 'WI', 'WV', 'WY'],
actions: {
// For dropdown handling
chooseState(state) {
this.set('company.state', state);
//Ember.set(this, "counties", this.get('ajax').request(config.host + '/api/counties/' + state).then((json) => json.items));
//this.set('counties', this.get('ajax').request(config.host + '/api/counties/' + state).then((json) => json));
},
chooseCounty(countyName) {
this.set('company.county', countyName);
},
chooseCompanyType(companyType) {
this.set('company.companyType', companyType);
},
}
});
And here is the route and model hook:
// routes/companies/edit.js
export default Ember.Route.extend({
model(params) {
var store = this.store;
return Ember.RSVP.hash({
companies: store.findRecord('company', params.company_id),
companyTypes: store.findAll('companyType')
});
}
});
The route that gets the companyType model is:
// routes/company-types.js
export default Ember.Route.extend({
model() {
return this.get('store').findAll('company-type');
}
});
And my models:
// models/company.js
export default DS.Model.extend({
companyName: DS.attr('string'),
street: DS.attr('string'),
county: DS.attr('string'),
city: DS.attr('string'),
state: DS.attr('string'),
zip: DS.attr('string'),
phone: DS.attr('string'),
email: DS.attr('string'),
fax: DS.attr('string'),
companyType: DS.attr('string')
});
// models/company-type.js
export default DS.Model.extend({
companyType: DS.attr('string')
});
Looking at Ember Inspector the data for the companyType is there and is a string, per my model. When I select a value from the dropbox, the data type turns into <svegbackend#model:company-type::ember1326:Environ Engineer. When I select one of the other drop downs, the value stays a string which I guess makes sense since the source for those are string arrays.
So how do I get the drop down to display the value when the form loads?
The problem is that, the companyType of the company is of type string where as the options list of the third select are of type companyType model. This creates a mismatch in setting the selected option initially.
Define the third power select as follows:
{#power-select class="select"
selected=company.companyType
options=companyTypesOptions
onchange=(action "chooseCompanyType")
as |name|
}}
{{name}}
{{/power-select}}
and define companyTypesOptions within edit-new-form.js as follows:
companyTypesOptions: Ember.computed('companyTypes.[]', function() {
return this.get('companyTypes').map((companyType)=> {
return Ember.get(companyType, 'companyType');
});
})
By this way; you will make both the options list and the selected value of type string! Do not forget if the type of the options and the selected you pass are different; you will get into trouble! Try to avoid that!

Get data from ember data bind it to a widget in view

I have a router that returns data from the data model.
I want to use this data to bind it to a widget in a view.
Model:
myApp.Unit = DS.Model.extend({
active: DS.attr('boolean'),
allowdecimals: DS.attr('boolean'),
name: DS.attr('string'),
count: DS.attr('number'),
});
Router:
myApp.EunitsRoute = Ember.Route.extend({
model: function() {
return this.store.find('unit');
},
setupController: function(controller, model) {
this._super(controller, model);
controller.set('units', model);
},
actions: { ...
In the view I expect an object formated as follows:
[ {"id": 1,"active": true,"allowdecimals": true,"name": "Pint","count": 8},
{"id": 2,"active": true,"allowdecimals": true,"name": "Each","count": 8},
...]
What I am getting now in the view is an object:<DS.RecordArray:ember400>
View:
var source10 = {
datatype: "array",
datafields: [
{ name: 'id' },
{ name: 'name' },
{ name: 'allowdecimals' },
{ name: 'active' },
{ name: 'count' }
],
localdata: controller.get('units')
};
var dataAdapter10 = new $.jqx.dataAdapter(source10);
$("#eunits_grid").jqxGrid({
pageable: true,
theme: 'energyblue',
autorowheight : true,
rowsheight : 50,
pagesize: 10,
source: dataAdapter10,
....
Template:
<script type="text/x-handlebars" data-template-name="eunits">
<div class="col-md-12">
<h3 class="page-header">Edit Units</h3>
{{#if adding}}
{{view AddnewunitView}}
{{/if}}
{{view UnitsView id='eunits_grid'}}
</div>
</script>

EmberJS - Sorting data prior to showing

I have a set of json data I get from server, what I need is to sort them before I show to screen.
Data Example:
{
"statuses": [
{
"id": 1,
"title":"Post title 1",
"date":"2014-12-20T11:30:48+0000",
"sticky":true,
"comments":[]
},
{
"id": 2,
"title":"Post title 2",
"date":"2014-12-25T11:30:48+0000",
"sticky":false,
"comments":[]
},
{
"id": 3,
"title":"Post title 3",
"date":"2014-12-15T11:30:48+0000",
"sticky":true,
"comments":[]
},
{
"id": 4,
"title":"Post title 4",
"date":"2014-12-10T11:30:48+0000",
"sticky":false,
"comments":[]
}
]
}
I need to
Show sticky statuses first sticky: true sort by date descending.
After then show normal statuses sticky: false sort by date descending
So far I was just able to list them in given data order. You can see the example here http://jsfiddle.net/sisir/kqxz71sg/2/
Resolved
Final working version is given in jsfiddle, I am also adding it here in case the jsfiddle link becomes obsolete in future.
HTML
<div id="main"></div>
<script type="text/x-handlebars" data-template-name="index">
{{input type="text" value=title}}
<button {{action "addStatus"}}>Submit</button>
{{#each status in sortedStatuses}}
<p {{bind-attr class="status.sticky:sticky"}}>{{status.title}}</p>
{{/each}}
</script>
JS
App = Ember.Application.create({
rootElement: '#main'
});
App.ApplicationAdapter = DS.FixtureAdapter;
App.Store = DS.Store.extend();
var attr = DS.attr(),
string = DS.attr('string'),
boolean = DS.attr('boolean'),
number = DS.attr('number'),
hasMany = DS.hasMany(),
date = DS.attr('date', {
defaultValue: function() { return new Date(); }
});
App.Status = DS.Model.extend({
sticky: boolean,
title: string,
date: date,
comments: attr
});
App.Status.reopenClass({
FIXTURES: [
{
"id": 1,
"title":"Post title 1",
"date":"2014-12-20T11:30:48+0000",
"sticky":true,
"comments":[]
},
{
"id": 2,
"title":"Post title 2",
"date":"2014-12-25T11:30:48+0000",
"sticky":false,
"comments":[]
},
{
"id": 3,
"title":"Post title 3",
"date":"2014-12-15T11:30:48+0000",
"sticky":true,
"comments":[]
},
{
"id": 4,
"title":"Post title 4",
"date":"2014-12-10T11:30:48+0000",
"sticky":false,
"comments":[]
}
]
});
App.IndexRoute = Ember.Route.extend({
setupController: function(controller){
var statuses = this.store.find('status');
controller.set('statuses', statuses);
}
});
App.IndexController = Ember.Controller.extend({
sortedStatuses: function(){
var statuses = this.get('statuses');
var stickyStatuses = statuses.filterBy('sticky').sortBy('date').reverse();
var nonStickyStatuses = statuses.filterBy('sticky', false).sortBy('date').reverse();
var sortedStatuses = stickyStatuses;
sortedStatuses.pushObjects(nonStickyStatuses);
return sortedStatuses;
}.property('statuses.#each'),
actions: {
addStatus: function(){
console.log('ok');
var status = {
title: this.title,
date: new Date(),
sticky: true
}
var status = this.store.createRecord('status', status);
status.save();
}
}
});
css
.sticky{
background: yellow;
}
Create a new computed property called sortedStatuses as follows:
App.IndexController = Ember.Controller.extend({
sortedStatuses: function(){
var statuses = this.get('statuses');
var stickyStatuses = statuses.filterBy('sticky').sortBy('date').reverse();
var nonStickyStatuses = statuses.filterBy('sticky', false).sortBy('date').reverse();
var sortedStatuses = stickyStatuses;
sortedStatuses.pushObjects(nonStickyStatuses);
return sortedStatuses;
}.property('statuses.#each')
});
In your template, you can then loop over sortedStatuses
{{#each status in sortedStatuses}}
<p {{bind-attr class="status.sticky:sticky"}}>{{status.title}}</p>
{{/each}}
Working example here

Loading state for ApplicationRoute

Using: ember 1.7.0
I have some server-side data that I want to load up in my ember app before any routes are transitioned to. Multiple (but not all) of my other routes / controllers need this data. I was thinking that I could just load up this data in the ApplicationRoute model method. It works fine, but does not display a loading state.
Is it possible to have the ApplicationRoute display a loading state until it's model promise gets resolved.
Here's a jsbin illustrating the problem: http://jsbin.com/soqivo/1/
Thanks for the help!
Update:
As of 1.11.0 release, it should be possible to define a loading substate for the application route.
TL;DR;
I think this is by design, but not a design flaw. This particular issue is happening because that long model request is taking place in ApplicationRoute#model when it should be in IndexRoute#model. Move that promise/request into the index route and it should be fine. If you must add stuff to the application controller, consider this, combined with something that says "loading" in your index.html file while the app is waiting.
Why
Ember.Route has a number of hooks that we often override so it does what we want instead of a default implementation. The most obvious hook being model and setupController. But sometimes we simply don't write the setuptController method because it does what we want it to do already (given one just wants to set the model into the controller). But regardless of these methods being overridden, they will run as part of an internal workflow anyway. This workflow has a number of steps that are not often discussed because they already do what we want and we tend to forget about them and their importance, and, as for this particular issue, the order in which these methods get called in the route life cycle.
App = Ember.Application.create();
App.logs = Ember.ArrayProxy.create({
content: []
});
App.Router.map(function() {
this.resource('posts', function() {});
});
function loggingAlias(property) {
return function() {
App.logs.pushObject(this._debugContainerKey + ' ' + property);
return this._super.apply(this, arguments);
};
}
App.LoggingRoute = Ember.Route.extend({
enter: loggingAlias('enter (private)'),
exit: loggingAlias('exit (private)'),
activate: loggingAlias('activate'),
deactivate: loggingAlias('deactivate'),
serialize: loggingAlias('serialize'),
deserialize: loggingAlias('deserialize (private)'),
model: loggingAlias('model'),
setupController: loggingAlias('setupController'),
afterModel: loggingAlias('afterModel'),
beforeModel: loggingAlias('beforeModel'),
renderTemplate: loggingAlias('renderTemplate'),
redirect: loggingAlias('redirect')
});
App.LogsController = Ember.ArrayController.extend({
content: App.logs,
actions: {
clearLogs: function() {
App.logs.clear();
}
}
});
App.ApplicationRoute = App.LoggingRoute.extend();
App.PostsRoute = App.LoggingRoute.extend();
App.PostsIndexRoute = App.LoggingRoute.extend();
/* Put your CSS here */
html,
body {
margin: 20px;
}
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Ember Route Hook Order" />
<meta charset="utf-8">
<title>Ember Route Hook Order</title>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/2.1.0/normalize.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.2.1.js"></script>
<script src="http://builds.emberjs.com/beta/ember.js"></script>
</head>
<body>
<script type="text/x-handlebars">
<strong>Note:</strong> <em>
MilkyWayJoe says: I didn't write this. I have found in jsbin at: http://jsbin.com/rolo/2/edit?output
<br />
Added here in case the link goes kaput just to point out the order of Ember.Route internal workflow steps
</em>
<br />
<br />{{link-to 'Index' 'index'}} {{link-to 'Posts' 'posts'}} {{outlet}} {{render 'logs'}}
</script>
<script type="text/x-handlebars" id='logs'>
<h3>Logged Method Calls</h3>
<a href="#" {{action 'clearLogs'}}>Clear Logs</a>
<ul>
{{#each}}
<li>{{this}}</li>
{{/each}}
</ul>
</script>
</body>
</html>
Since renderTemplate is the last to get called so it only makes sense that it doesn't render anything until the promise(s) within a given route get resolved.
For child routes, that's totally fine because their loading substate will have some type of canvas to draw onto, since a parent-already-loaded-living-and-breathing-route has been loaded prior this route even being instantiated. But that's not true for the ApplicationRoute since it has no parent route or template to rely upon, thus rendering a blank page until all promises get resolved.
Working snippet
The next best thing is moving any long running requests to a child route. As the proposed solution, I've moved your 3 sec promise to IndexRoute#model since this route will run anyway and is the direct child of ApplicationRoute by default. I would say reserve the application route or controller for handling error events instead.
App = Em.Application.create({
displayName: 'Test.App'
});
App.Router.map(function() {
this.resource('files', function() {
this.route('index', {path: '/'});
this.resource('file', { path: ':file_id' }, function() {
this.route('index', {path: '/'});
this.route('detail');
});
});
});
App.FilesController = Em.ArrayController.extend();
App.FilesFileController = Em.ObjectController.extend();
App.Person = Ember.Object.extend({});
App.IndexRoute = Ember.Route.extend({
model: function(params, transition){
return new Ember.RSVP.Promise(function(resolve){
Ember.run.later(function(){
var model = App.Person.create();
resolve(model);
}, 3000);
});
}
});
App.LoadingRoute = Em.Route.extend({
renderTemplate: function() {
this.render('loading', {
into: 'application',
outlet: 'loading'
});
}
});
App.FileLoadingRoute = App.LoadingRoute.extend();
App.FilesRoute = Em.Route.extend({
model: function() {
var selfie = this;
return new Ember.RSVP.Promise(function(resolve){
Ember.run.later(function() {
var model = selfie.store.find('file');
resolve(model);
}, 800);
});
}
});
App.FilesIndexRoute = Em.Route.extend({
model: function(){
return this.store.all('file');
}
});
App.FileRoute = Em.Route.extend({
model: function(params) {
return this.store.find('file', params.file_id);
}
});
App.FileIndexRoute = Em.Route.extend({
model: function() {
return this.modelFor('file');
},
renderTemplate: function() {
this.render('files/index', {
into: 'application'
});
this.render('file/index', {
into: 'files/index',
outlet: 'file'
});
}
});
App.FileDetailRoute = Em.Route.extend({
model: function() {
var selfie = this;
return new Ember.RSVP.Promise(function(resolve){
Ember.run.later(function(){
var file = selfie.modelFor('file');
var model = selfie.store.find('fileDetail', file.id);
resolve(model);
}, 800);
});
},
renderTemplate: function() {
this.render('files/index', {
into: 'application'
});
this.render('file/index', {
into: 'files/index',
outlet: 'file'
});
this.render('file/detail', {
into: 'file/index',
outlet: 'detail'
});
},
actions: {
loading: function() {
return true;
}
}
});
App.RlLoadIndicatorComponent = Em.Component.extend({
classNames: ['rl-load-indicator'],
classNameBindings: ['isLoading:rl-overlay:rl-silent'],
overlay: true,
spinner: true,
message: 'Loading...',
loading: false,
isLoading: function() {
return this.get('loading');
}.property('loading'),
spinnerClass: function() {
if (this.get('loading')) {
if (this.get('spinner')) {
return 'rl-spinner';
}
}
return "";
}.property(),
actions: {
setLoading: function() {
this.set('loading', true);
},
setDone: function() {
this.set('loading', false);
}
}
});
App.ApplicationAdapter = DS.FixtureAdapter.extend();
App.File = DS.Model.extend({
name: DS.attr('string'),
text: DS.attr('string'),
detail: DS.belongsTo('fileDetail', {async: true})
});
App.FileDetail = DS.Model.extend({
owner: DS.attr('string'),
canEdit: DS.attr('bool'),
file: DS.belongsTo('file'),
property1: DS.attr('string'),
property2: DS.attr('string'),
property3: DS.attr('string'),
property4: DS.attr('string'),
property5: DS.attr('string')
});
App.File.FIXTURES = [
{id: 1, name: 'File 1', text: 'Blah 1', detail: 1},
{id: 2, name: 'File 2', text: 'Blah 2', detail: 2},
{id: 3, name: 'File 3', text: 'Blah 3', detail: 3},
{id: 4, name: 'File 4', text: 'Blah 4', detail: 4},
{id: 5, name: 'File 5', text: 'Blah 5', detail: 5},
{id: 6, name: 'File 6', text: 'Blah 6', detail: 6},
{id: 7, name: 'File 7', text: 'Blah 7', detail: 7},
{id: 8, name: 'File 8', text: 'Blah 8', detail: 8},
{id: 9, name: 'File 9', text: 'Blah 9', detail: 9},
{id: 10, name: 'File 10', text: 'Blah 10', detail: 10}
];
App.FileDetail.FIXTURES = [
{
id: 1,
owner: 'Spiderman',
canEdit: true,
file_id: 1,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'With great values, comes great bindings'
},
{
id: 2,
owner: 'Iron Man',
canEdit: true,
file_id: 2,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'Another Value'
},
{
id: 3,
owner: 'Thor',
canEdit: false,
file_id: 3,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'Another Value'
},
{
id: 4,
owner: 'Captain America',
canEdit: false,
file_id: 4,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'Another Value'
},
{
id: 5,
owner: 'Neil DeGrasse Tyson',
canEdit: true,
file_id: 5,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'Another Value'
},
{
id: 6,
owner: 'Dr. Doom',
canEdit: false,
file_id: 6,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'Another Value'
},
{
id: 7,
owner: 'Reed Richards',
canEdit: true,
file_id: 7,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'Another Value'
},
{
id: 8,
owner: 'Walter White',
canEdit: true,
file_id: 8,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'Say My Name!'
},
{
id: 9,
owner: 'Jesse Pinkmann',
canEdit: true,
file_id: 9,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'Bitch'
},
{
id: 10,
owner: 'Hawk Barton',
canEdit: false,
file_id: 10,
property1: 'Value 1',
property2: 'Value 2',
property3: 'Value 3',
property4: 'Value 4',
property5: 'Another Value'
}
];
/* Put your CSS here */
html, body {
margin: 20px;
}
.rl-load-indicator {
text-align: center;
}
.rl-overlay {
position:fixed;
top:0;
left:0;
right:0;
bottom:0;
background-color:rgba(0, 0, 0, 0.85);
background: url(data:;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuNUmK/OAAAAATSURBVBhXY2RgYNgHxGAAYuwDAA78AjwwRoQYAAAAAElFTkSuQmCC) repeat scroll transparent\9; /* ie fallback png background image */
z-index:9999;
color:white;
}
.rl-silent {
display: none;
visibility: hidden;
}
.rl-spinner {
width: 30px;
height: 30px;
background-color: #27ae60;
margin: 100px auto;
margin-bottom: 8px;
-webkit-animation: rotateplane 1.2s infinite ease-in-out;
animation: rotateplane 1.2s infinite ease-in-out;
}
.arrow-right {
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid green;
}
#-webkit-keyframes rotateplane {
0% { -webkit-transform: perspective(120px) }
50% { -webkit-transform: perspective(120px) rotateY(180deg) }
100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg) }
}
#keyframes rotateplane {
0% {
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
} 50% {
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
} 100% {
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Loading Thingy" />
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.3.0.js"></script>
<script src="http://builds.emberjs.com/tags/v1.7.0/ember.js"></script>
<script src="http://builds.emberjs.com/beta/ember-data.js"></script>
</head>
<body>
<script type="text/x-handlebars">
<h1>{{unbound App.displayName}}</h1>
{{partial "menu"}}
<hr />
{{outlet}}
{{outlet "loading"}}
</script>
<script type="text/x-handlebars" data-template-name="loading">
{{rl-load-indicator loading=true}}
</script>
<script type="text/x-handlebars" data-template-name="_menu">
{{#link-to 'index'}}Home{{/link-to}} | {{#link-to 'files.index'}}Files{{/link-to}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<h3>Index</h3>
Content goes here
</script>
<script type="text/x-handlebars" data-template-name="files/index">
<h3>Files</h3>
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th> </th>
</tr>
</thead>
<tbody>
{{#each file in model}}
<tr>
<td>{{file.id}}</td>
<td>{{file.name}}</td>
<td>
{{#link-to 'file.index' file}}
<p class="arrow-right"></p>
{{/link-to}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{outlet "file"}}
</script>
<script type="text/x-handlebars" data-template-name="file/index">
<h3>{{name}}</h3>
{{text}}
<hr />{{#link-to 'file.detail'}}Detail{{/link-to}}
{{outlet "detail"}}
</script>
<script type="text/x-handlebars" data-template-name="file/detail">
<h5>Details</h5>
<hr />
<ul>
<li>owner: {{owner}}</li>
<li>can edit: {{canEdit}}</li>
<li>property 1: {{property1}}</li>
<li>property 2: {{property3}}</li>
<li>property 3: {{property3}}</li>
<li>property 4: {{property4}}</li>
<li>property 5: {{property5}}</li>
</script>
<script type="text/x-handlebars" data-template-name="components/rl-load-indicator">
<div {{bind-attr class=spinnerClass}}></div>
{{unbound message}}
</script>
</body>
</html>
Just create a different resource below the application route, and do all of your loading there. Don't use the index route though, it is only hit when you hit the root of a particular resource (App.IndexRoute would be when you just hit the root of your application).
App = Ember.Application.create();
App.Router.map(function() {
this.resource("top",function(){ // a place you can grab things for the app and block
this.resource('home'); // a place you want to get when everything is ready
});
});
App.ApplicationRoute = Ember.Route.extend();
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo("home");
}
});
App.TopRoute = Ember.Route.extend({
// This does trigger a loading state
model: function(params){
return new Ember.RSVP.Promise(function(resolve){
setTimeout(function(){
resolve();
}, 3000); // 3 second delay, wooh, your server is slow!!!
});
}
});
http://jsbin.com/mivul/edit?html,js,output

ember.js how to set title of option for Ember.Select

I am a starter of Ember and I try to use Ember.js(1.0.0.pre) in my app.
I am trying to set title for my Ember.Select's options to show tips when mouseover.
But, I can't find any information about the option's title in API.
Do I have to write a function myself to populate the "title" attribute?
Is there any way like "optionLabelPath" to bind "title" attribute for options?
To achieve this we need to reopen the Ember.SelectOption
here is the fiddle for the following example
MyApp = Ember.Application.create();
Ember.SelectOption.reopen({
attributeBindings: ['title'],
title: function() {
var titlePath = this.getPath('parentView.optionTitlePath');
return this.getPath(titlePath);
}.property('parentView.optionTitlePath')
});
MyApp.selectArray = [{
label: "A",
id: "1",
title: "for Apple"
},
{
label: "B",
id: "2",
title: "for Ball"
}];
Handlebars
<script type="text/x-handlebars" >
{{view Ember.Select
contentBinding="MyApp.selectArray"
optionLabelPath="content.label"
optionValuePath="content.id"
optionClassPath="content.title"
}}
</script>​
​
Here is the simplest I could come up with:
http://jsfiddle.net/aK8JH/1/
Template:
{{view MyApp.Select contentBinding="content"}}
View:
MyApp.Select = Ember.Select.extend({
attributeBindings: ['title'],
title: 'myTitle'
});
Read this: http://emberjs.com/documentation/#toc_attribute-bindings-on-a-view
Below is what I've got after observing source code in Ember:
Ember.SelectOption.reopen({
attributeBindings: ['title'],
init: function() {
this.titlePathDidChange();
this._super();
},
titlePathDidChange: function() {
var titlePath = this.get('parentView.optionTitlePath');
if (!titlePath) { return; }
Ember.defineProperty(this, 'title', Ember.computed(function() {
return this.get(titlePath);
}).property(titlePath));
}.observes('parentView.optionTitlePath')
});