Cannot access model property on class definition - javascript

I send value to model as attribute
Views.App = Backbone.View.extend({
initialize: function () {
this.items = new Models.Items()
.on('sync:subitems', function (item) {
this.subitems = new Models.Subitems({itemId: item.attributes.id});
And successfully receive it in initilize of model
var Subitems = Models.Subitems = Backbone.Collection.extend({
initialize: function(attributes, options) {
this.itemId = attributes.itemId;
console.log(this.itemId);
},
model: Subitem,
url: './subitems?item_id=' + encodeURIComponent(this.itemId)
});
console.log returns the value of attribute in initialize.
But request is sent like:
'./subitems?item_id=undefined'
Why do I have undefined if I have access to the property in initialize? How can it be fixed?

Change url to a function and you'll be in the context of the backbone collection as appose to the window.

Related

How to send collection to another view?

Is there anyway to send backbone collection to another view without listenTo methods, to send it like an array or something else.
Im doing the fetch in the initialize function and then putting the collection in my array is that bad?
this.userModels = [];
this.collectionUser = new app.types.Users();
this.collectionUser.fetch();
this.userModels.push(this.collectionUser);
Im trying to send it like an array but on refreshing my web page sometimes im getting this
this.options child {
length: 15,
models: Array[15],
_byId: Object,
_listenId: "l4",
_events: Object…
}
and sometime getting with zero values
this.options child {
length: 0,
models: Array[0],
_byId: Object,
_listenId: "l4",
_events: Object…
}
So i wanna send my collection without listenTo method if it's possible.
First view:
app.types.FirstView = Backbone.View.extend({
initialize: function() {
this.collectionUser = new app.types.Users();
this.collectionUser.fetch();
};
sendCollection: function() {
var secondView = new app.types.SecondView({
collection: this.collectionUser
});
}
});
Second view:
app.types.SecondView = Backbone.View.extend({
initialize: function(options) {
this.collection = options.collection;
// so i want to get this.collectionUser here without listenTo
// method and without fetch here is that possible ? I said
// sometimes i get it sometimes not when i refersh my web page
// when i render it first time.
};
});
Yes you can send everything with js and use initialize for that view.
In your view you need to declare initialize function like this.
var someView = Backbone.View.extend({
template: _.template('some html file'),
initialize: function(options){
this.collection = options.collection
},
events: {
'click .someclass': 'doSomthing',
'click #someId': 'doSomthingElse'
},
doSomthing: function(event){
event.preventDefault();
var that = this;
that.collection.fetch({
success: function(){
that.$('element').append(that.collection);
}
});
},
render: function(){
var that = this;
that.$el.html(that.template);
return this;
}
});
And when u make new instance of your view need pass your collection as argument.
this.collectionUser = new app.types.Users();
this.view = new someView({collection: this.collectionUser});
This is it

Passing parameters to a Backbone View (id, className and so on)

I have some code that makes a Backbone.View, based on some params I pass to it, like so:
// The Form View
var FormView = Backbone.View.extend({
initialize: function (opts) {
debugger; // This is here only to figure out what gets executed first: if "id" method or "initialize"
this.options = {};
this.options.id = opts.id;
this.options.className = opts.class;
},
id: function () {
debugger; // The application will stop here before the debugger I set in the initialize method
return this.options.id; // options is undefined!
},
className: function () {
return this.options.className; // options is undefined!
}
});
// The params
var params =
fid: "some-form",
class: "form-horizontal"
};
var myForm = new FormView(params);
But the this.options property is always undefined. As I can see, the method that sets the view's properties runs BEFORE the initialize method. As a workaround I think I could access the initialize method inside de id callback and call its arguments, but I'm not sure how to do this properly. And I don't think this is a good approach either.
Any ideas? - Thanks in advance.
Why don't you use the usual way of passing options to the view? Something like:
var FormView = Backbone.View.extend({
initialize: function () {
this.foo = this.options.foo;
this.bar = this.options.bar;
}
});
var params = {foo: '1', bar: '2'};
var v = new FormView(params);
You can also pass as params {id: '1', className: 'your-class'} and Backbone will apply it automatically to the respective id and className properties of the target View.
You don't seem to be initializing the options attribute properly. You should have
initialize: function (opts) {
this.options = {}; // you were missing this part
this.options.id = opts.id;
this.options.className = opts.class;
},

Accessing model ID in backbone.js

I’m building my first Backbone application, and I’m a little confused with how I pass an ID into a model. When I instantiate the model, I pass in the ID like this var user = new UserModel(id);. At that point, id == 1. The value is still the same in the initialize
method in the model. When I use that variable in the url property, it’s undefined. Why is that?
// Filename: models/user/UserModel.js
define([
'underscore',
'backbone'
], function(_, Backbone) {
var UserModel = Backbone.Model.extend({
initialize: function(id) {
console.log('modelID: ' + id); // Prints 'modelID: 1'
this.set({'id': id});
},
// Sends GET request to http://[domain]/users/view/undefined
url: 'users/view/' + this.id
});
return UserModel;
});
This one works:
var UserModel = Backbone.Model.extend({
initialize: function(id) {
console.log('modelID: ' + id); // Prints 'modelID: 1'
this.set({'id': id});
},
// Sends GET request to http://[domain]/users/view/undefined
url: function(){
return "/users/view/"+this.get("id");
}
});
console.log(new UserModel("10").url())
http://jsfiddle.net/wyA9Q/2/
A Backbone model expects an object representing the attributes as first argument to its constructor
constructor / initialize new Model([attributes], [options])
When creating an instance of a model, you can pass in the initial values of the attributes, which will be set on the model. If you define an initialize function, it will be invoked when the model is created.
Setting model.urlRoot will help build your URLs
urlRoot model.urlRoot or model.urlRoot()
Specify a urlRoot if you're
using a model outside of a collection, to enable the default url
function to generate URLs based on the model id. "[urlRoot]/id"
Attributes should be accessed via model.get
So you could define your model as
var UserModel = Backbone.Model.extend({
urlRoot: '/users/view'
});
and instantiate it as var user = new UserModel({id: id});
var userModel = new UserModel({id: 10});
userModel.fetch();
It should work :)

Backbone.js view variables being overwritten

I am creating views via a $.each and the myId attribute of all the views always ends up being overwritten by the myId of the last element.
Creation of views
$('.form').each(function() {
// split class name
var classNameArray = $(this).attr('class').split('-');
// get typeId from last part of classname
var myId = classNameArray[classNameArray.length-1];
new myView({ 'el': $('.form-' + myId), 'myId': myId });
});
Initialization of my view
var myView = Backbone.View.extend({
events: {
},
initialize: function() {
var myId = this.options.myId;
},
test: function() {
console.log(myId); // will return myId of last view created
}
});
How can I get the views to keep their unique myId's?
When you write it like this --
initialize: function() {
var myId = this.options.myId;
},
It creates a variable local to the initialize function (that's a Javascript thing, not a Backbone thing).
Try this instead (create a variable local to the View object):
initialize: function() {
this.myId = this.options.myId;
},
test: function() {
console.log(myId); // will return myId of last view created
}
this [myId] is not the [myId] in :
initialize: function() {
var myId = this.options.myId;
}
it is the [myId] from :
$('.form').each(function() {
// split class name
var classNameArray = $(this).attr('class').split('-');
// get typeId from last part of classname
var myId = classNameArray[classNameArray.length-1]; //from this myId!!!
new myView({ 'el': $('.form-' + myId), 'myId': myId });
});
because:
first:
"var myId = this.options.myId; "
this [myId] is the initialize within the local variables,you can not access this variable outside the method.
second:
console.log(myId); // will return myId of last view created
why are we here be able to access to [myId]?because this [myId] is the [this.myId],[this] is the context of the calling method :
new myView({ 'el': $('.form-' + myId), 'myId': myId });
so,this [myId] is the :
var myId = classNameArray[classNameArray.length-1];
[myId] here.this [myId] is cyclic change, so you always get the last cycle the value of the [myId].
solution:
initialize: function() {
this.myId = this.options.myId;
},
because [this.myId] is [myView]'s internal variables, each time you create the instance of [myView], in the [initialize] method dynamically the [this.myId] is set to the correct value form [this.options.myId].
kind of problem, you can refer to this article:
http://dmitrysoshnikov.com/ecmascript/chapter-4-scope-chain

Fetch data having a specific id defined in the view instance

I need to fetch data having a specific id
and which id is defined in the view instance.
Here the example, see the comments in MyModel definition:
// my view instance
var myView = new MyView({
model: {id: 12321}
});
MyView = Backbone.View.extends({
initialize: function()
{
myModel.fetch();
}
});
MyModel = Backbone.Model.extends({
url: function url ()
{
// how to get the id passed to view instance?
return "http:..../id/" + this.id;
}
});
Model should not has any knowledge of the existence of the View, so the View should be the one that sais to the Model which id to fetch:
MyView = Backbone.View.extends({
initialize: function()
{
myModel.id = this.model.id;
myModel.fetch();
}
});
(I've used your example code as template for my example, but I have to say I feel several weird things on it, I suppose is just a matter of taste)
Update: My very personal taste opinions
Is very difficult to do this but as you requested I'll share with you my very personal code review of your example code. Take this as it is: a very humble opinion.
this.model confused
I would not use attribute names that can create confussion:
var myView = new MyView({
model: {id: 12321}
});
Into this instance this.model is making reference to a raw Hash but in a Backbone context this is against the intuitive feeling that this is gonna be a Backbone.Model.
I rather change it for something like this:
var MyView = Backbone.View.extend({
initialize: function( opts ){
this.model_id = opts.model_id;
}
})
var myView = new MyView({ model_id: 12321 });
I think this naming is more intuitive.
close variables scopes
This code can only works if myModel is in an scope bigger that it should be:
MyView = Backbone.View.extends({
initialize: function()
{
myModel.fetch();
}
});
I rather prefer using more encapsulated scopes, even if myModel has been declared in the out-side context of your View the View should use a variable of its private context. For example
var MyView = Backbone.View.extends({
initialize: function( opts ) {
this.model = opts.model;
this.model.fetch();
}
});
var myView = new MyView({ model: myModel });
Check the detail that I have also added var in front of MyView because if not MyView will be a window global variable.
use the Backbone urlRoot
In your example, this ...
MyModel = Backbone.Model.extends({
url: function url ()
{
// how to get the id passed to view instance?
return "http:..../id/" + this.id;
}
});
... can be summarized as this:
MyModel = Backbone.Model.extends({
urlRoot: "http:..../id"
});

Categories

Resources