I'm creating a small multiplayer games using ember on the frontend.
I have a games list in the homepage, I want to show the amount of cards there are present in a game too.
App.Game = DS.Model.extend({
serverSeedHash: DS.attr(),
serverSeed: DS.attr(),
table: DS.belongsTo('table'),
bingoCards: DS.hasMany('bingoCard')
});
App.BingoCard = DS.Model.extend({
player: DS.attr(),
clientSeed: DS.attr(),
game: DS.belongsTo('game'),
player: DS.belongsTo('player')
});
App.GamesRoute = Ember.Route.extend({
model: function () {
return Ember.RSVP.hash({
games: this.store.find('game'),
bingoCards: this.store.find('bingoCard')
});
},
setupController: function (controller, model) {
controller.setProperties(model);
}
});
App.GamesController = Ember.ArrayController.extend({
needs: ['game']
});
App.GameController = Ember.ObjectController.extend({
amountOfCards: function () {
return this.get('bingoCards.length');
}.property('bingoCards.#each')
});
Whenever I go to a specific game I can access the amountOfCards property just fine by typing {{amountOfCards}} inside the game template.
However, when I try to display it on the homepage, it won't work in the each loop.
{{#each game in games}}
<tr>
<td>{{game.id}}</td>
<td>{{amountOfCards}} {{game.amountOfCards}}</td>
<td>{{#link-to 'game' game.id}}Join{{/link-to}}</td>
</tr>
{{/each}}
Basically my question is: I have multiple games, each game has multiple bingoCards. I want compute a property per game based on the bingoCards. How can I do this?
You're gonna have to specify an itemController that will wrap each individual game into a controller (usually an ObjectController) of your choice.
Template
{{#each game in controller}}
<tr>
<td>{{id}}</td>
<td>{{amountOfCards}}</td>
<td>{{#link-to 'game' id}}Join{{/link-to}}</td>
</tr>
{{/each}}
Route
App.GamesRoute = Ember.Route.extend({
model: function() {
return Ember.RSVP.all([
this.store.find('game'),
this.store.find('bingoCard')
]);
},
setupController: function(controller, model) {
var games = model[0];
controller.set('content', games);
}
});
Controllers
App.GamesController = Ember.ArrayController.extend({
itemController: 'game'
});
App.GameController = Ember.ObjectController.extend({
amountOfCards: function () {
return this.get('bingoCards.length');
}.property('bingoCards.#each', 'bingoCards.length')
});
You can read more about it on the Ember API
Related
I need help with my code, I'm trying to learn Backbone for my Social Project. I'm trying to render a view from a collection that I got from an API (deployd API)
Here is the HTML code for the table:
<div class="container-fluid">
<table id= "teachers">
<thead>
<tr>
<th>Name</th>
<th>Last Name</th>
<th>Code</th>
<th>Last time online</th>
</tr>
</thead>
<tbody id="table-body"></tbody>
</table>
</div>
<script type="text/template" id="teacher-template">
<td><%= name %></td>
<td><%= lastname %></td>
<td><%= code %></td>
<td><%= lastactivity %></td>
</script>
Here is the JS code:
var TeacherModel = Backbone.Model.extend({
defaults: {
id:'',
name: '',
lastname: '',
code: '',
lastactivity: ''
}
});
var TeacherCollection = Backbone.Collection.extend({
url: "/teachers",
model: TeacherModel
});
var teachercollection = new TeacherCollection();
teachercollection.url = '/teachers';
teachercollection.fetch({
success: function(collection, response) {
console.log("Done!!");
}, error: function(collection, response) {
alert(response);
}
});
var TeachersView = Backbone.View.extend({
el: '#table-body',
initialize: function() {
this.render();
},
render: function() {
this.$el.html('');
teachercollection.each(function(model) {
var teacher = new TeacherView({
model: model
});
this.$el.append(teacher.render().el);
}.bind(this));
return this;
}
});
var TeacherView = Backbone.View.extend({
tagName: 'tr',
template: _.template($('#teacher-template').html()),
render: function() {
this.$el.html(this.template(this.model.attributes));
return this;
}
});
// Launch app
var app = new TeachersView;
So my question is, how I can pass a collection to a view, or a model of the collection to a view? I want to render the data in each row from the table. The browser gets the collection, as you can see here:
I've been trying for days, and I just can't understand the logic, I have read the documentation, and a little of the Addy Osmani's book but just can't get my head on it, can someone explain it to me? Been looking for answers in this site but some on them include some "add models" stuff, which confuse me more.
(The parameters of the model in the image, differ from the code. I'd translate to make it more easy to understand.)
how I can pass a collection to a view, or a model of the collection to a view?
You are already doing that in your code:
var teacher = new TeacherView({
model: model
});
Here you're passing a model to view's constructor using model option.
You can pass a collection to view via it's constructor like:
var app = new TeachersView({
collection:teachercollection
});
Which you can access inside the view via this.collection and this.model respectively.
var TeachersView = Backbone.View.extend({
el: '#table-body',
initialize: function() {
this.render();
},
render: function() {
this.$el.html('');
this.collection.each(function(model) {
this.$el.append(new TeacherView({
model: model
}).el);
},this);
return this;
}
});
Note that fetch() is asynchronous, so you'll need to wait till it succeeds before rendering the view.
See the suggestions in this answer regarding the changes I made to your render method.
this answer might help understanding a thing or two.
I'm trying to achieve the following with Ember-CLI:
After an initial list of items is loaded, the user can select a city from the dropdown to see only those items that are interesting to him/her. In my case that's districts in cities. You can select from a dropdown list a city to see
only districts in that city.
Ideally, all should happen without calling an separately (on click).
So far, I've got this, but the console.log for 'filteredContent' returns an array of 0 elements. Any hints where I'm doing something wrong?
district/index.hbs:
<p>{{view "select" content=cities optionValuePath="content.id" optionLabelPath="content.name" selection=selectedCity}}</p>
{{#each item in filteredContent}}
<p>{{item.name}} in {{item.city.name}}</p>
{{/each}}
route:
var DistrictListRoute = Ember.Route.extend({
model: function () {
return this.store.find('district');
},
setupController: function(controller, model) {
this._super(controller, model);
this.store.find('city').then(function(cities) {
controller.set('cities', cities);
});
}
});
export default DistrictListRoute;
controller:
export default Ember.Controller.extend({
filteredContent: [],
selectedCity: null,
selectedCityChanged: function () {
var selectedCity = this.get('selectedCity');
console.log(selectedCity);
var filteredContent = this.get('model').filterBy('city', selectedCity);
console.log(filteredContent);
}.observes('selectedCity')
});
model:
export default DS.Model.extend({
city: DS.belongsTo('city', {async: true}),
name: DS.attr('string'),
advert: DS.hasMany('item')
});
Finally figured it out:
Controller:
export default Ember.ArrayController.extend({
selectedCity: null,
filteredContent: [],
selectedCityChanged: function () {
var selectedCity = this.get('selectedCity');
var filteredContent = this.get('model').filterBy('city.id', selectedCity.id);
this.set('filteredContent', filteredContent);
}.observes('selectedCity')
And then, handlebars template needed some tweaking:
<p>{{view "select" content=cities optionValuePath="content.id" optionLabelPath="content.name" selection=selectedCity}}</p>
{{#if filteredContent}}
<h2>District in {{selectedCity.name}}</h2>
{{#each district in filteredContent}}
<p>{{district.name}} in {{district.city.name}}</p>
{{/each}}
{{else}}
<h2>Districts</h2>
{{#each district in content}}
<p>{{district.name}} in {{district.city.name}}</p>
{{/each}}
{{/if}}
I have a Book and a Chapter collection. In a template called book_list.html there's an each statement listing all the book items:
<!-- book_list.html -->
<template name="bookList">
<div class="book-list">
{{#each books}}
{{> bookItem}}
{{/each}}
</div>
In order to get the word count I created a helper in book_item.js which works by fetching all the chapters in the book and returning the sum of all of their words.
Everything was OK, until I decided to remove the autopublish package and use publish and subscribe instead. The problem now is that I don't know how to do get the ID of the current book in book_list since its ID is not present in the URL (book_list is the home page).
This is the code (minus the code for the word count):
//publications.js
Meteor.publish("books", function() {
return Books.find({});
});
Meteor.publish("chapters", function(bookId) {
return Chapters.find({
bookId: bookId
}, {
sort: {
position: 1
}
});
});
//route.js
Router.map(function() {
this.route("bookList", {
path: "/",
waitOn: function() {
return Meteor.subscribe("books");
},
data: function() {
return Books.find({});
}
});
});
//book_item.js
Template.bookItem.helpers({
words: function() {
var chapters = Chapters.find({
bookId: this._id
}).fetch();
// code for the word counter
I'm trying to display the names of each department. I handmade a 'department' model based off of another model i made that does work. Despite them being identical, #each will not loop through the 'departments' and list them.
departments.hbs >
{{#each model}}
<tr>
<td>
{{#linkTo 'department' this}}{{this.departmentName}}{{/linkTo}}
</td>
<td>{{this.departmentName}}</td>
</tr>
{{/each}}
No errors. It just doesn't list the departments.
VpcYeoman.DepartmentsView = Ember.View.extend({
templateName: 'departments'});
VpcYeoman.DepartmentView = Ember.View.extend({
templateName: 'department'
});
VpcYeoman.DepartmentsController = Ember.ObjectController.extend({
// Implement your controller here.
});
VpcYeoman.Department = DS.Model.extend({
departmentName: DS.attr('string'),
departmentMembers: DS.attr('string')
});
VpcYeoman.Department.reopen({
// certainly I'm duplicating something that exists elsewhere...
attributes: function(){
var attrs = [];
var model = this;
Ember.$.each(Ember.A(Ember.keys(this.get('data'))), function(idx, key){
var pair = { key: key, value: model.get(key) };
attrs.push(pair);
});
return attrs;
}.property()
});
VpcYeoman.Department.FIXTURES = [
{
id: 0,
departmentName: "Sickness",
departmentMembers: "61"
},
{
id: 1,
departmentName: "Health",
departmentMembers: "69"
}
];
'department/#/' DOES work. Why is {{#each model}} not able to find the list of departments?
EDIT:
VpcYeoman.DepartmentsController = Ember.ArrayController.extend({
// Implement your controller here.
});
Upon entering {{log model}} before the {{#each model)) loop, I get this response:
[nextObject: function, firstObject: undefined, lastObject: undefined, contains: function, getEach: function…]
__ember1386699686611_meta: Meta
length: 0
__proto__: Array[0]
VpcYeoman.DepartmentsRoute = Ember.Route.extend({
renderTemplate: function() {
this.render();
}
});
VpcYeoman.DepartmentRoute = Ember.Route.extend({});
You need to declare a DepartmentsRoute with the following:
VpcYeoman.DepartmentsRoute = Ember.Route.extend({
model: function() {
return this.store.find('department');
}
});
DepartmentsController should probably be an ArrayController, and you can view the model in the console to validate it has something using ((log model)) before your each
You need to implement a model hook, returning the departments
VpcYeoman.DepartmentsRoute = Ember.Route.extend({
model: function(){
return this.store.find('department');
},
renderTemplate: function() {
this.render();
}
});
the department route is guessing based on the route name and implementing the default model hook.
I have a model setup with Ember fixtures. My model is like the following:
App.Question = DS.Model.extend({
isCompleted: DS.attr('boolean'),
question_top: DS.attr('string'),
question_bottom: DS.attr('string'),
etc......
});
My fixtures (the actual data) is like the following:
App.Question.FIXTURES = [
{
id: 1
},
{
id: 2
}
];
I want to create a unordered list in my template that shows a "li" item for each record in my Fixtures. I think I need to use the {{#each question}} syntax but when I do {{#each question}}, it doesn't work.
How do I loop through my Fixtures data to create a unordered list, with one list item for each record in my Fixtures data?
Probably your question property doesn't exist in your controller. If you are doing:
App.QuestionRoute = Ember.Route.extend({
model: function() {
return this.store.find('question');
}
});
You can use:
<h2>Questions:</h2>
<ul>
{{#each model}}
<li>{{question_top}}</li>
{{/each}}
</ul>
Give a look in that fiddle http://jsfiddle.net/marciojunior/25GHN/
You need to return it to a route's model hook:
http://emberjs.jsbin.com/UGEmEXEy/1/edit
App.IndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('question');
}
});
App.QuestionAdapter = DS.FixtureAdapter;
App.Question = DS.Model.extend({
isCompleted: DS.attr('boolean'),
question_top: DS.attr('string'),
question_bottom: DS.attr('string')
});
App.Question.FIXTURES = [
{
id: 1,
isCompleted: true
},
{
id: 2,
isCompleted: false
}
];