newbie mistake? JSON and Ember - ember.js

new here to ember, and very much trying to learn - and learn where I'm going wrong.
I'm being fed json that looks like this:
"status": "success",
"data": {
"groups": [
{
"id": 2,
"name": "Test1234",
"kind": "Happy",
"parent_group_id": 1,
"children_count": {
"boy": 10,
"girl": 4,
"pets": 2
},
"is_top_level": true
},
The path to get this info would be /api/groups/top.
I have a (what I believe would be) simple app.js:
App = Ember.Application.create();
App.Router.map(function() {
this.route("login", {path: "/"});
this.route("groups");
this.resource('about');
});
App.GroupsRoute = Ember.Route.extend({
model: function() {
return App.Group.find('top');
}
});
App.LoginController = Ember.Controller.extend({
actions: {
login: function(username, password){
jQuery.ajax({
url: "/api/auth",
type: 'post',
data: JSON.stringify( { "username": "user", "password": "pass" } ),
contentType: 'application/json',
dataType: 'json',
async: false,
success: function(result) {
if (result.status === 'success') {
user = result.data.user;
App.User.id = user.id;
App.User.name = user.name;
App.User.isAuthenticated = true;
App.User.displayUnits = "F";
} else {
//debugger;
throw "The! username and/or password you have entered is incorrect, please try again ";
return false;
}
},
error: function(xhr, status, errorOut) {
throw "The? username and/or password you have entered is incorrect, please try again ";
return false;
}
});
if (App.User.isAuthenticated)
this.transitionToRoute('groups');
}}
});
App.RESTAdapter = RL.RESTAdapter.create({
host: 'http://localhost:3000',
namespace: 'api/'
});
App.Client = RL.Client.create({
adapter: App.RESTAdapter
});
App.User = RL.Model.extend({
username: RL.attr('string'),
id: RL.attr('string'),
isAuthenticated: RL.attr('boolean'),
});
App.Group = RL.Model.extend({
id: RL.attr('string'),
name: RL.attr('string'),
kind: RL.attr('string')
});
App.RESTAdapter = RL.RESTAdapter.create({
defaultData: { cookie: "data"}
});
I'm trying to display each "group" in my template. For example {{#each groups}} {{name}} {{/each}}, but no luck - I can see the JSON data in the response in inspector, and no errors - but still, nothing coming trough.
Any help?
Thanks!
Ptep
edit - template:
<script type="text/x-handlebars">
{{outlet}}
</script>
<script type="text/x-handlebars" id="groups">
<h3>Hello,
{{#each groups}}
{{name}}! <br>
{{kind}}, {{id}}
{{/each}}
</h3>
</script>

The array itself would be the context of your template, so you would either use
{{#each}}{{name}}{{/each}}
or
{{#each model}}{{name}}{{/each}}
or
{{#each controller}}{{name}}{{/each}}
or
{{#each item in controller}}{{item.name}}{{/each}}

Related

You modified *** twice in a single render

After upgrading to 1.13 I get this exception and I can't figure out what's the issue. I also couldn't find any helpful resource which tackles my issue.
It happens for properties I set in another computed property. But this property is definitely called only once.
I have created a jsbin example: http://emberjs.jsbin.com/roderameya/edit?html,js,console,output
UPDATE
As requested I post some code which is more close to my real implementation.
Ember.Controller.extend({
filter: '',
resultCount: {
total: 0,
matches: 0,
mismatches: 0
},
results: function() {
var items = this.get('model'),
matches = [],
resultCount = {};
// Apply search filter
matches = items.filter(function(item){
// Just a dummy filter function
return true;
});
// We need the total number matched by the filter string
resultCount.total = matches.length;
// The already matched items must be narrowed further down
matches = matches.filter(function(item) {
// Another filter function
return true;
});
resultCount.matches = matches.length;
resultCount.mismatches = resultCount.total - matches.length;
this.set('resultCount', resultCount);
return matches;
}.property('model', 'filter'),
});
Try to have your properties not set other properties, but rather depend on each other:
App.IndexController = Ember.Controller.extend({
count: function() {
return this.get("data.length") || 0;
}.property('data.length'),
data: [1,2,3]
});
Updated jsbin for you.
UPDATE
Basically, your resultCount is a temporary variable that we can get rid of, and the rest are just chaining computed properties together:
updated jsbin for advanced example
code:
// Index controller
App.IndexController = Ember.Controller.extend({
count: Ember.computed('filteredItems.length', function(){
return this.get('filteredItems.length');
}),
data: [
Ember.Object.create({ name: "jim", age: 15 }),
Ember.Object.create({ name: "jeff", age: 42 }),
Ember.Object.create({ name: "eric", age: 7 })
],
filter: RegExp(".*"),
ageFilter: -1,
mismatchCount: Ember.computed('filteredItems.length', 'secondPassFilteredItems.length', function() {
return this.get('filteredItems.length') - this.get('secondPassFilteredItems.length');
}),
filteredItems: Ember.computed('data', 'filter', function() {
var controller = this;
return this.get('data').filter(function(item) {
return item.get('name').match(controller.get("filter"));
});
}),
secondPassFilteredItems: Ember.computed('filteredItems', 'ageFilter', function() {
var controller = this;
var ageFilter = controller.get("ageFilter");
if (Ember.isEqual(ageFilter, -1)) {
return this.get('filteredItems');
} else {
return this.get('filteredItems').filter(function(item) {
// more filtering
return item.get("age") <= ageFilter;
});
}
}),
results: Ember.computed.alias('secondPassFilteredItems'),
actions: {
filterByJ: function() {
this.set('filter', new RegExp("j"));
},
filterByEric: function() {
this.set('filter', new RegExp("eric"));
},
filterAllNames: function() {
this.set('filter', new RegExp(".*"));
},
filterYoungins: function() {
this.set('ageFilter', 15);
},
filterAllAges: function() {
this.set('ageFilter', -1);
}
}
});
Template usage:
<script type="text/x-handlebars" data-template-name="index">
<p>Results found: {{count}}</p>
<p>Diff between first and second filter: {{mismatchCount}}</p>
<p>First Filter:
<button {{action 'filterAllNames'}}>all people</button>
<button {{action 'filterByJ'}}>People with J in name</button>
<button {{action 'filterByEric'}}>People named 'eric'</button>
</p>
<p> Second Filter:
<button {{action 'filterAllAges'}}>all ages</button>
<button {{action 'filterYoungins'}}>15 years old or younger</button>
</p>
<ul>
{{#each results as |item|}}
<li>{{item.name}} is {{item.age}} years old</li>
{{/each}}
</ul>
</script>

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>

How to get List for hasMany relation in Fixture adapter in ember-data

I am new to ember.. I have 2 models..
Music.Artist = DS.Model.extend({
name: DS.attr('string'),
dob : DS.attr('date'),
songs : DS.hasMany('song',{async:true})
});
Music.Artist.FIXTURES=[
{
id:1,
name:'John',
dob:new Date(),
songs:['1','2']
},
{
id:2,
name:'Robbin',
dob:new Date(),
songs:['1','2']
}
];
Music.Song = DS.Model.extend({
title:DS.attr('string'),
artists:DS.hasMany('artist',{async:true})
});
Music.Song.FIXTURES = [
{
id:1,
title:'A day to remember',
artists:[1,2]
},
{
id:2,
title:'Cant live without you',
artists:[1,2]
}
];
I want for url "/songs/id"... I get all the songs that has an artist with the given id.
Music.Router.map(function(){
this.resource('songs',{path:'/songs/:id'});
});
Music.SongsRoute = Ember.Route.extend({
model:function(param){
var artist = this.store.find('artist',param.id);
return artist.get('songs');
}
});
But it returns undefined... How to get the list of songs that are related to the Artist.
Is there any way i can achieve this by using only routes.
How to read the array of songs, if not through get.
Based on the current versions of Ember (1.6.1) and Ember-Data (1.0.0-beta.9), here's how I got your example working. I changed your route naming, I think you really want something like /artists/:artist_id which will list the artist's data, including all his songs.
Your Artist and Song model declarations seem fine, but I declared the fixtures like so:
Music.Artist.reopenClass({
FIXTURES: [
{
id:1,
name:'John',
dob:new Date(),
songs:['1','2']
},
{
id:2,
name:'Robbin',
dob:new Date(),
songs:['1','2']
}
]
});
Music.Song.reopenClass({
FIXTURES: [
{
id:1,
title:'A day to remember',
artists:[1,2]
},
{
id:2,
title:'Cant live without you',
artists:[1,2]
}
]
});
For the router:
Music.Router.map(function() {
this.resource('artists');
this.resource('artist', { path: '/artists/:artist_id' });
});
For the routes:
var Music.ArtistsRoute = Ember.Route.extend({
model: function() {
return this.store.find('artist');
}
});
var Music.ArtistRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('artist', params["artist_id"]);
}
});
For your templates:
// artists.hbs
<ul>
{{#each}}
<li>{{#link-to 'artist' this}}{{name}}{{/link-to}}</li>
{{/each}}
</ul>
// artist.hbs
<h1>{{name}}</h1>
<hr>
<h2>Songs</h2>
<ul>
{{#each songs}}
<li>{{title}}</li>
{{/each}}
</ul>
Hope this helps!

How to set a textbox value in Ember.js

forgive me if this question is too silly .I'm studying Ember.js myself and I'm stuck with a problem I need to set a value of the textbox dynamically and I dont know how to do that now I'm using jquery for overcome this error by using $("#results")[0].value = data; and I know its not the right way How can I do the same in Ember,js
my Current code is given below
App = Em.Application.create();
App.BaseCurrency = Em.Object.extend({
id: null,
name: null
});
App.DestCurrency = Em.Object.extend({
id: null,
name: null
});
App.BaseSelector = Em.ArrayController.extend({
content: [
App.BaseCurrency.create({ id: "INR", name:" Indian Rupee (INR)" }),
App.BaseCurrency.create({ id: "USD", name: "US Dollar (USD)" })
]
});
App.baseSelector = App.BaseSelector.create();
App.DestSelector = Em.ArrayController.extend({
content: [
App.DestCurrency.create({ id: "INR", name: " Indian Rupee (INR)" }),
App.DestCurrency.create({ id: "USD", name: "US Dollar (USD)" })
]
});
App.destSelector = App.DestSelector.create();
App.ConvertCurrency = Em.ObjectController.extend({
content: [],
amount:0,
baseCur: null,
destcur: null,
result: 0,
convert: function () {
var amount = this.get('amount');
var from = this.get('baseCur');
var to = this.get('destCur');
$.ajax({
type: "POST",
url: "Home/ConvertCurenncy",
data: "{amount:" + amount + ",from:'" + from + "',to:'" + to + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
$("#results")[0].value = data;
}
});
}
});
App.convertCurrency = App.ConvertCurrency.create();
and html
<script type="text/x-handlebars">
AMOUNT : {{view Ember.TextField valueBinding="App.convertCurrency.amount"}}
BASE : {{view Ember.Select contentBinding="App.baseSelector" optionLabelPath="content.name" optionValuePath="content.id" valueBinding="App.convertCurrency.baseCur" }}
DEST : {{view Ember.Select contentBinding="App.destSelector" optionLabelPath="content.name" optionValuePath="content.id" valueBinding="App.convertCurrency.destCur" }}
<button id="btnConvert"{{action "convert" target="App.convertCurrency"}}>convert</button>
RESULT :<input type="text" readonly=true id="results" />
</script>
You where almost there, what you might do is to customize a Ember.Texfield, for example:
App.ResultField = Ember.TextField.extend({
type: 'text',
attributeBindings: ['readonly'],
readonly: true
})
and then use it like so:
Result: {{view App.ResultField valueBinding="App.convertCurrency.result"}}
then in your success callback you set App.convertCurrency.result to the received value:
...
success: function (data) {
App.convertCurrency.set('result', data);
}
...
and bindings will take care on updating your textfield's value
Hope it helps.

emberjs pre-4 and ember-data: no data on browser-refresh

If I browse from the index to a game, the data is shown, because of {{#linkTo}}s context, but if I'm refreshing the site, every time the game name doesn't show up.
EDIT: Here is a fiddle, but unfortunately the fiddle-version with the fixture adapter works properly, even with ken's suggestion to remove the model from the game-template.
the returned data from /api/games is as follows:
{
"games":[
{
"id":1,
"name":"First Game"
}
]
}
and the returned data from /api/games/1
{
"game": [
{
"id": 1,
"name": "First Game"
}
]
}
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="games">
<ul>{{#each game in controller}}
<li>{{#linkTo 'game' game}}{{game.name}}{{/linkTo}}</li>
{{/each}}</ul>
</script>
<script type="text/x-handlebars" data-template-name="game">
<h1>Name:{{model.name}}</h1>
</script>
<script type="text/javascript">
App = Ember.Application.create();
App.Game = DS.Model.extend({
name: DS.attr('string')
});
App.Store = DS.Store.extend({
revision: 11,
adapter: DS.RESTAdapter.create({
namespace: 'api'
})
});
App.GamesController = Ember.ArrayController.extend({
content: []
});
App.GameController = Ember.ObjectController.extend({
content: null
});
App.Router.map(function(match) {
this.route("games", { path : "/" });
this.route("game", { path : "/games/:game_id" });
});
App.GameRoute = Ember.Route.extend({
model: function(params) {
return App.Game.find(params.game_id);
}
});
App.GamesRoute = Ember.Route.extend({
setupController: function(controller) {
controller.set('content', App.Game.find());
}
});
</script>
Has anyone an idea?
Remove model from your game template, try this instead
<script type="text/x-handlebars" data-template-name="game">
<h1>Name:{{name}}</h1>
</script>
JSFiddle your code to see where the problem is
The response from my server for a single game was wrong. I had an array with a single object in it, but I used the Object controller, so I fixed it with just responding with
{
"game": {
"id": 1,
"name": "First Game"
}
}