I'm having trouble getting data from iron:router.
Im trying to get the data by param._id and then pass it to my template.created to set a session variable for editing purposes.
Here is my code in the router:
Router.route('/edit/:_id', function(){
this.render('edit', {
data: function(){
return Collection.findOne({_id: this.params._id})
}
})
})
And then I want to access that data here:
Template.edit.created = function(){
data = ???
Session.set('edit', data)
$(input).val(data.post)
}
If i do console.log( this ) I get Blaze.TemplateInstance.
But when I console.log(this) in Template.edit.events I get the document I want from the iron:router.
I've used Template.currentData(); and managed to access the data in template.created but can someone explain why "this" in template.created and template.events refers to 2 different things?
For template.created and template.rendered you can access the data with this.data.
Related
Let's say I have a templateA.html with input fields and then another separate templateB.html which is supposed to display the values of the input fields from templateA.html as they are typed in. I've gotten it to work with Session.set and Session.get but the problem is the input values stay the same when the page is refreshed and it doesn't seem the best way to do this. I then tried to use ReactiveVar but since I can't find any good examples on how to use it I'm a bit lost. The following is how it works with Session so maybe this will help understand what I'm trying to do with ReactiveVar.
Template.templateA.events({
'change #batch_form': function(){
var batch_num = document.getElementById('batch_number').value;
var dist_name = document.getElementById('distributor_name').value;
var data = {
batch_number: batch_num,
dist_name: dist_name
}
Session.set('form_data', data);
}
})
Template.templateB.helpers({
input_data(){
return Session.get('form_data');
},
});
TemplateB.html
<template name='templateB'>
<p>Batch #:{{input_data.batch_number}}</p>
<p>Batch #:{{input_data.dist_name}}</p>
</template>
You should avoid Session where you can. Better scope your Template-exceeding variables with a shared scope. ES6 import/export are suitable for that.
Consider you want to share a ReactiveDict (which behaves like Session) as state between only those two Templates. You can create a new js file with the following content:
shared.js
import { ReactiveDict } from 'meteor/reactive-dict'
export const SharedAB = new ReactiveDict()
This gives you the control to share the state only between those Templates, that import the object.
templateA.js
import { SharedAB } from './shared.js'
Template.templateA.events({
'change #batch_form': function(){
var batch_num = document.getElementById('batch_number').value;
var dist_name = document.getElementById('distributor_name').value;
var data = {
batch_number: batch_num,
dist_name: dist_name
}
SharedAB.set('form_data', data);
}
})
templateB.js
import { SharedAB } from './shared.js'
Template.templateB.helpers({
input_data(){
return SharedAB.get('form_data');
},
});
if they don't have any parent-child relationship you can use common ReactiveDict variable(here Session) to pass the data between just like you're doing.
but the problem is the input values stay the same when the page is
refreshed and it doesn't seem the best way to do this
for this on onDestroyed callback of template you can clear the Session variable values
Template.templateA.onDestroyed(function(){
Session.set('form_data', false); // or {}
})
so when you come back to this page/template, there is no data to display.
I have a web service that returns an object called response. It has an object data. When I do the following:
var myObject = JSON.stringify(response.data);
console.log("My Results: " + myObject);
[{"id":"1","username":"sam","user_id":"1","status":"1"}]
But I am having trouble accessing these objects in a scope.
for example
$scope.myresponse = response.data;
$scope.myresponse.username = response.data.username
It doesn't work. I even tried $scope.myresponse = response.data[0]; that didnt' work either. Any suggestions?
Store response return from backend call inside a service layer variable and access that variable from controller to get the required result.
Demo code showing above interaction...
In ServiceLayer.js
var myObject = response["data"];
function getMyObject() {
return myObject;
}
In Controller.js
Inject that registered service and access myObject variable.
$scope.myresponse = this.serviceLayer.getMyObject();
use this myResponse variable to access any required information.
Regards
Ajay
Actually the solution turned out be an easy one. Not very clean but it works.
$scope.myData = response.data;
$scope.myResults = $scope.myData[0];
After this I was able to access all the elements e.g. id by {{myResults.id}} in my view.
Thank you all for your help.
I am using a rails server that returns this JSON object when going to the '/todos' route.
[{"id":1,"description":"yo this is my todo","done":false,"user_id":null,"created_at":"2015-03-19T00:26:01.808Z","updated_at":"2015-03-19T00:26:01.808Z"},{"id":2,"description":"Shaurya is awesome","done":false,"user_id":null,"created_at":"2015-03-19T00:40:48.458Z","updated_at":"2015-03-19T00:40:48.458Z"},{"id":3,"description":"your car needs to be cleaned","done":false,"user_id":null,"created_at":"2015-03-19T00:41:08.527Z","updated_at":"2015-03-19T00:41:08.527Z"}]
I am using this code for my collection.
var app = app || {};
var TodoList = Backbone.Collection.extend({
model: app.Todo,
url: '/todos'
});
app.Todos = new TodoList();
However, when trying to fetch the data it states that the object is undefined. I originally thought that my function wasn't parsing the JSON correctly. However, that doesn't look to be the case. I created a parse function with a debugger in it to look at the response. In gives back, an array with three objects.
Here what happens when I try testing the fetch().
var todos = app.Todos.fetch()
todos.length // returns undefined
todos.get(1) // TypeError: undefined is not a function
The todos collection doesn't automatically populate the function get() in console. I am running out of ideas of what can be the problem. Please help. Thanks!
Fetch is a ayncronous, you need to listen to the add event:
var todos = app.Todos.fetch()
todos.on('add', function(model){
console.log(todos.length);
});
If you pass the parameter reset, you could listen for the would new models:
var todos = app.Todos.fetch({reset: true})
todos.on('reset', function(model){
console.log(todos.length);
});
You could also read here.
There are two problems:
Fetch is asynchronous; we don't know exactly when we'll have a result, but we do know that it won't be there when you are calling todos.length.
Fetch sets the collection's contents when it receives a response; calling app.Todos.fetch() will result in app.Todos containing whatever models were fetched by the request. Its return value is not useful for inspecting the collection, so var todos = app.Todos.fetch() won't give you what you want in any case.
If you want to inspect what you receive from the server, your best option is to set a success callback:
app.Todos.fetch({
success: function (collection, response, options) {
console.log(collection);
}
});
I am trying to work with Ember.js
Can I expose my data model as JSON through a route or controller?
I have an object like this saved in the store:
this.store.createRecord('Person', {
id: 1,
name: this.get('name'),
email: this.get('email')
});
I want to expose this data from a route or controller as JSON object. I don't want to use any view.
Is it possible to do this?
Thanks for help!
EDIT
My route is:
App.ResultRoute = Ember.Route.extend({
model: function() {
return this.store.find('person', 1);
}
});
There is '1' because I want only this record.
In this way It works and I see in the view the {{name}} and the {{email} of the Person object.
I want to see only the JSON, I tried to do how you suggest me :
App.ResultRoute = Ember.Route.extend({
afterModel: function (model) {
model.get('content').forEach(function (item) {
console.log(item.get('content'));
});
}
});
But I receive this error:
Uncaught Error: Assertion Failed: Error: More context objects were passed than there are dynamic segments for the route: error
What is my error?
The way I would do this would be, I would have an api in my model which would return a plain json object to whoever asked it. So the Person model would have a getPersonDetails method which will hide all the internal details, including the attributes and associations and whatever else, and return the state of the person object it is invoked upon.
So, for example, if you wanted to display a table of persons or something, you would do a createRecord, and just ask the newly created person object for it's details.
Start from the beginning of this guide. http://emberjs.com/guides/routing/specifying-a-routes-model/ It will show you how to specify a model for a route.
Then, read this entire guide on controllers: http://emberjs.com/guides/controllers/
In general, you would access that data from the route's model hook with:
this.store.find('person') // All records
If you wanted to access that first object as JSON, you could do:
var person_JSON = this.store.find('person').then(function (persons) {
//The persons records are now available so you can do whatever you want with them
console.log(persons.objectAt(0).get('content'));
});
You could also iterate over all records and strip out the content to produce raw json without the Ember wrapping... Just depends on what you need to really do.
Really the best place to put this would be the route's afterModel hook, though. You wouldn't be working with a promise, as Ember would have dealt with that for you:
afterModel: function (model) {
model.get('content').forEach(function (item) {
console.log(item.get('content'));
});
}
Hope that helps.
Edit: Since you have one record try this:
afterModel: function (model) {
console.log(model.get('content'));
}
I need to work with backbone.js, i can't go to "render" part inside my view here is my code:
var Vigne = {
Models:{},
Collections: {},
Views:{},
Templates:{}
}
Vigne.Models.Raisin = Backbone.Model.extend({})
Vigne.Collections.Grape = Backbone.Collection.extend({
model: Vigne.Models.Raisin,
url: "./scripts/data/vin.json",
initialize: function (){
console.log("grape initialised");
}
});
Vigne.Views.Grape= Backbone.View.extend({
initialize: function(){
_.bindAll(this,"render");
this.collection.bind("reset",this.render);
},
render: function(){
console.log("render");
console.log(this.collection.length);
}
})
Vigne.Router = Backbone.Router.extend({
routes:{
"": "defaultRoute"
},
defaultRoute: function(){
console.log("defaultRoute");
Vigne.grape = new Vigne.Collections.Grape()
new Vigne.Views.Grape ({ collection : Vigne.grape });
Vigne.grape.fetch();
console.log(Vigne.grape.length);
}
}
);
var appRouter= new Vigne.Router();
Backbone.history.start();
I am expecting it to display my collection's length in the debugger's console, it seem's like it doesn't reset. Any ideas?
Edit:
i added this within the fetch function:
success: function(){
console.log(arguments);
},
error: function() {
console.log(arguments);
}
});
and the fetch function succeed on getting the json file, but it doesn't trigger the reset function.
i solved this problem by setting the attribute within the fetch function to true:
Vigne.grape.fetch({
reset:true,
error: function() {
console.log(arguments);
}
}
);
This book helped me : http://addyosmani.github.io/backbone-fundamentals/
Backbone calls reset() on fetch success which in turns triggers reset event. But If your fetch fails due to some reason, you won't get any event. So you have to pass an error handler in fetch method and use it to identify the error and handle it.
Vigne.grape.fetch({
error: function() {
console.log(arguments);
}
});
You can also pass success call back and you will be able to know the problem in your fetch.
You can also use Charles proxy/Chrome Debuuger Tool to identify if you are getting proper response from your backend.
Can you please paste your response what you are getting from server. You may vary the data but just keep the format right.
Edit:
One more problem I can see is that you have not defined attributes in your model So after Backbone fetch, it refreshes your collection with the new models fetched from server. Fetch method expects an array of json objects from server and each json object in response array should match with the attributes you have set in defaults in your model Otherwise it won't be able to create new models and hence won't be able to refresh your collection. Can you please rectify this and let me know.