I'm having trouble getting relationship data from localstorage when loading a model in the route.
The first time I get the data from the server through an ajax request everything is fine but as soon as I get to a new route and reload the data all the relationship have disappeard.
I don't understand how to reload these relationship! Ideally I would like to call the user-exam model and get all the hasMany array as well.
thanks for your help.
here are my two models
import DS from 'ember-data';
exam-question.js:
export default DS.Model.extend({
question : DS.attr('string'),
questionID : DS.attr('string'),
answer1 : DS.attr('string'),
answer2 : DS.attr('string'),
answer3 : DS.attr('string'),
answer4 : DS.attr('string'),
answer5 : DS.attr('string'),
answer6 : DS.attr('string'),
answer7 : DS.attr('string'),
numberOfAnswers : DS.attr('number'),
solutions : DS.attr('string'),
examID : DS.attr('string'),
chosenAnswers : DS.attr('string'),
result : DS.attr('string'),
userexam: DS.belongsTo('user-exam')
});
user-exam.js:
import DS from 'ember-data';
export default DS.Model.extend({
salesforceid : DS.attr('string'),
name : DS.attr('string'),
examType: DS.attr('string'),
resultPercentage : DS.attr('number'),
result : DS.attr('string'),
numberOfQuestions : DS.attr('number'),
rightAnswers : DS.attr('number'),
passingPercentage : DS.attr('string'),
questions: DS.hasMany('exam-question')
});
on my account.js route
import Ember from 'ember';
export default Ember.Route.extend({
model: function () {
return this.store.find('user-exam');
},
afterModel: function() {
var applicationController = this.controllerFor('application');
if (!applicationController.isLoggedIn) {
this.transitionTo('index');
}
this.controllerFor('account').send('loadData');
}
});
& controller (on first load I manage to populate all data and relationships are mapped perfectly)
import Ember from 'ember';
export default Ember.ArrayController.extend({
needs: ['application', 'newexam-modal'],
isLoading: true,
actions:{
loadData: function (){
console.log(this);
this.send('loadExamTypes');
this.send('LoadUserExams');
},
LoadUserExams: function () {
var applicationController = this.get('controllers.application');
var store = this.store;
var accountController = this;
var userexams = store.findAll('user-exam');
accountController.setProperties ({isLoading: true});
userexams.then(function() {
var userProperties = applicationController.getProperties('useremail','currentToken');
var requestdata = '{ "action": "GetExams","useremail":"'+userProperties.useremail+'","secretToken":"'+userProperties.currentToken+'"}';
Ember.$.ajax({
url: "my server url",
type: "POST",
contentType: "application/json",
data: requestdata,
success : function (data) {
//window.console.log(data);
if (userexams.content.get('length') !== data.get('length')){
data.forEach(function (item){
var examname = item.Name;
store.find('user-exam', { name: examname }).then(function(){
},function() {
console.log("items"+item);
store.createRecord('user-exam', {
salesforceid : item.Id,
name : item.Name,
resultPercentage : item.Exam_Result_Percentage__c,
result : item.Exam_Result__c,
numberOfQuestions : item.Number_of_Questions__c,
rightAnswers : item.Right_Answers__c,
passingPercentage : item.Passing_Percentage__c,
examType : item.Exam_Type__r.Name
}).save().then(function (createdexam){
console.log(item.Exam_Questions__r.records);
item.Exam_Questions__r.records.forEach(function (question){
store.createRecord('exam-question', {
question : question.Question__r.Question__c,
questionID : question.Name,
answer1 : question.Question__r.Answer_1__c,
answer2 : question.Question__r.Answer_2__c,
answer3 : question.Question__r.Answer_3__c,
answer4 : question.Question__r.Answer_4__c,
answer5 : question.Question__r.Answer_5__c,
answer6 : question.Question__r.Answer_6__c,
answer7 : question.Question__r.Answer_7__c,
numberOfAnswers : question.Question__r.Number_of_Answers__c,
solutions : question.Question__r.Solutions__c,
examID : question.Exam_Name__c,
chosenAnswers : question.Answer_Chosen__c,
result : question.Result__c,
userexam : createdexam
//store.find('user-exam', {name: item.Name})
}).save();
});
});
});
});
}
accountController.setProperties ({isLoading: false});
},
error : function (data) {
console.log(data);
}
});
});
},
deleteExamData: function() {
console.log('deleting user exams');
this.store.findAll('user-exam').then(function(record){
record.content.forEach(function(rec) {
console.log('deleting exam'+rec);
Ember.run.once(this, function() {
rec.deleteRecord();
rec.save();
});
}, this);
});
}
}
});
On my account template I use linkto to display the user-exam data. The first time I click on the button the data loads in template with all associated child records. But When I go back to account route and click on the view exam again the child records disappear
{{#link-to 'exam' this}}view exam »{{/link-to}}
here is my exam.js route
import Ember from 'ember';
export default Ember.Route.extend({
examid:'',
model: function(params){
return this.store.find('user-exam', params.exam_id);
},
serialize: function(model){
return {exam_id:model.get('id')};
},
setupController: function(controller, exam) {
controller.set('model', exam);
},
afterModel: function() {
var applicationController = this.controllerFor('application');
if (!applicationController.isLoggedIn) {
this.transitionTo('index');
}
this.controllerFor('exam').send('loadData' );
}
});
my exam.hbs
<div class="jumbotron">
<div class="container">
<h2>This is Exam: {{ name }} !</h2>
</div>
</div>
<div class="container">
{{ questions }}
{{#each question in questions}}
{{question.name}}<br />
{{/each}}
</div>
my router map:
Router.map(function() {
this.route('register');
this.route('application');
this.route('login');
this.route('account');
this.resource('exam', { path: 'exams/:exam_id' });
this.route('settings');
});
My localstorage setup is done like so with the ember-cli addon
my application.js adapter:
import DS from 'ember-data';
export default DS.LSAdapter.extend({
namespace: 'sfdquiz'
});
and serializer:
import DS from 'ember-data';
export default DS.LSSerializer.extend({
});
I was making a stupid error! question.name didn't exist.
{{#each question in questions}}
{{question.name}}<br />
{{/each}}
But I changed the pattern loading all the data at once was making the app too slow. I used the aftermodel to go fetch the related objects from the server and connect them to their parent at that moment.
model: function(params){
return this.store.find('user-exam', params.exam_id);
},
afterModel: function(exam) {
var applicationController = this.controllerFor('application');
if (!applicationController.isLoggedIn) {
this.transitionTo('index');
} else {
this.controllerFor('exam').send('loadData', exam.get('id'));
}
}
Related
I am trying to go to a new page after a successful login using Firebase and EmberFire.
Below is my controller.js for my sign in page
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
signIn(provider) {
let controller = this;
this.get('session').open('firebase', {
provider: provider,
email: this.get('email') || '',
password: this.get('password') || '',
}).then(() => {
controller.set('email', null);
controller.set('password', null);
}, (error) => {
console.log(error);
});
}
}
});
Below is my route.js for my sign in page
import Ember from 'ember';
export default Ember.Route.extend({
login: function() {
let controller = this.get('controller');
let email = controller.get('userEmail');
let password = controller.get('userPassword');
this.get('session').open('firebase', {
provider: 'password',
email: email,
password: password
}).then(function() {
this.transitionTo('protected');
}.bind(this));
}
});
below is my template.hbs
{{outlet}}
<form class="login">
<h3>Log in to BettorHalf</h3>
{{input
type='text'
class='form-control'
value=email
placeholder="Email address"
}}
{{input
type='password'
class='form-control'
value=password
placeholder='password'
}}
<button
class="signinbtn"
{{action 'signIn' 'password'}}
>
{{ 'sign-in'}} Sign In
</button>
</form>
I am trying to log a person in using Firebase auth and then going to a new page which will populate that persons information by querying the relevant data attached to a user.
Thanks for any help you can be, I am new to coding and pretty new to Ember and Firebase.
When using 'password' as your provider the login page controller.js file should handle the action, something like
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
signIn() {
let controller = this;
this.get('session').open('firebase', {
provider: 'password',
email: this.get('email') || '',
password: this.get('password') || '',
}).then(() => {
controller.set('email', null);
controller.set('password', null);
this.transitionToRoute('profile');
}, (error) => {
console.log(error);
});
}
}
});
Within a controller you use this.transitionToRoute() to goto the desired page.
I am prototyping an emberjs app. I am facing a problem when I try to save the data.
My model:
App.User = DS.Model.extend({
id: DS.attr('string'),
name: DS.attr('string'),
description: DS.attr('string')
});
My Controller:
App.UsersAddController = Ember.ArrayController.extend({
actions: {
addUser: function () {
var name = this.get('name');
var description = this.get('description');
if (!name.trim() && !description.trim()) {
return;
}
var user = this.store.createRecord('user', {
'id': 'id-' + Math.random().toString(36).substr(2, 16),
'name': name,
'description': description
});
this.set('id', '');
this.set('name', '');
this.set('description', '');
user.save();
}
}
});
My template:
{{input type="text" placeholder="Name" value=name class="name-input"}}
{{input type="text" placeholder="Description" value=description class="name-input"}}
<button {{action 'addUser'}} class="submit">Submit</button>
The event bubbles up to the right controller. But fails to save. I am a beginner with emberjs. Please help me out.
You should remove id attribute from model definition.
App.User = DS.Model.extend({
// no id
name: DS.attr('string'),
description: DS.attr('string')
});
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
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
}
];