Pass values between views in backbone - javascript

I have 2 views and need to pass values between them.
var appModel1 = Backbone.Model.extend({
url: '/',
defaults: {
name: 'Default name'
},
validate: function(attr){
}
});
var appCollection1 = Backbone.Collection.extend({
model: appModel1
});
var collection1 = new appCollection1();
var model1 = new appModel1();
model1.bind('change', function(){
model1.save();
});
var appView1 = Backbone.View.extend({
model: model1,
_modelDataBind: undefined,
el:'#container1',
initialize: function(){
this._modelDataBind = new Backbone.ModelBinder();
this.render();
},
render: function(){
var template = _.template($('#app1').html());
this.$el.html(template);
var bindings = {
name: '#txtName'
};
var changeTrigger = {
'changeTriggers': {
'': 'keyup',
'#txtName': 'keyup'
}
};
this._modelDataBind.bind(this.model, this.$el, bindings, changeTrigger);
},
'events': {
'click #btnSubmit': 'addRecord'
},
addRecord: function(){
collection1.push(model1);
var item = '<li>Name: ' + model1.get('name') + '</li>';
var app2 = new appView2({collection: collection1});
$('#txtName').val('').focus();
}
});
var view1 = new appView1({});
var appView2 = Backbone.View.extend({
el: '#container2',
initialize: function(){
this.render();
},
render: function(){
var template = _.template($('#app2').html());
this.$el.html(template);
this.collection.each(function(model){
var item = '<li>Name: ' + model.get('name') + '</li>';
$('#infoList').append(item);
});
}
});
var view2 = new appView2({});
As of now, I have only been able to pass values using collection and id variables.
Are they reserved variables?
Can i use any other variable to pass data?
var app2 = new appView2({nameObj: nameObj});
this fails.

As per docs, Backbone view only acts upon model, collection, el, id, className, tagName, attributes and events properties of options object.
However, you can pass any other data you want, the whole options object will be available as the first parameter of initialize callback.
For example:
var AppView = Backbone.View.extend({
el: '#container2',
initialize: function(options){
// access your data here
this.valuableInformation = options.valuableInformation;
if(!options.doNotRender)
this.render();
},
render: function(){
}
});
new AppView({
valuableInformation:"it's nothing",
doNotRender: true
});

Related

Cannot retrieve collection outside of the view

I'm making a simple list of people with option when clicking on person's name the Router will take a name as a parameter 'student/:name' and find a right person's object in a collection. I instantiate collection in a GroupView class by fetching it from the server. And that's where the Error appears: to get the access to collection (so I can find right object) in my viewStudent() method in Router class, I'm making one more instance of GroupView(), and console shows an error and that's right, 'cause there're no objects in collection.
I cannot wrap my head around this, why in GroupView() I receive data from the server and my collection just works fine, but second time I instantiate GroupView() in a Router - there's no collection? Maybe there's any other way I can get access to the collection in my Router? Any help would be greatly appreciated.
var StudentModel = Backbone.Model.extend({
defaults: {
name: 'Volodya',
lastName: 'Peterson',
age: 22,
gender: 'male'
}
});
var StudentsCollection = Backbone.Collection.extend({
model: StudentModel,
url: '/students.json'
});
var StudentView = Backbone.View.extend({
tagName: 'li',
template: _.template($('#studentTpl').html()),
events: {
'click': function () {
eventAggregator.trigger('student:selected', this.model);
}
},
render: function () {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
var GroupView = Backbone.View.extend({
tagName: 'ul',
initialize: function () {
this.collection = new StudentsCollection();
this.collection.on('update', this.render, this);
this.collection.fetch();
},
render: function () {
var self = this;
this.collection.each(function (student) {
var studentView = new StudentView({
model: student
});
self.$el.append(studentView.render().el);
});
$('body').html(this.$el);
}
});
var RouterView = Backbone.View.extend({
tagName: 'ul',
render: function () {
var self = this;
_.each(this.model.toJSON(), function (value) {
self.$el.append('<li>' + value + '</li>');
});
return this;
}
});
var GroupController = function () {
this.start = function () {
var groupView = new GroupView();
};
};
var Router = Backbone.Router.extend({
routes: {
'': 'index',
'student/:name': 'viewStudent'
},
index: function () {
groupController.start();
},
viewStudent: function (name) {
var groupView = new GroupView();
var selectedStudent = groupView.collection.find(function (student) {
return student.get('name') === name;
});
$('body').append((new RouterView({ model : selectedStudent})).render().el);
}
});
var eventAggregator= _.extend({}, Backbone.Events),
groupController;
$(function () {
var router = new Router();
groupController = new GroupController();
Backbone.history.start();
eventAggregator.on('student:selected', function (student) {
var urlpath= 'student/'+ student.get('name');
router.navigate(urlpath, {trigger: true});
});
});

After Adding a record it is not displaying the data immediately to the view

When I loads the page , it is getting all the datas and I am displaying the datas. But When I add a record, that is I am submitting the form "addcontact", the datas are creating in the database. But It is not adding into the collection and that this.collection.on('add') is not getting triggered. So, I think the problem was because of this. Can any one tell me that where I am doing wrong? Is there any other way to solve this.
This code works functionally, but the only problem with this is , on creating new record using this.collection.create({new post},{wait: true}); the values are getting updated in the database. But it is not adding into the collection.
(function(){
Backbone.emulateHTTP = true;
//Backbone.emulateJSON = true;
window.App = {
Models : {},
Collections: {},
Views : {},
Router : {}
};
window.vent = _.extend({},Backbone.Events);
window.template = function(id){
return _.template( $('#'+id).html() );
};
// Contact Model
App.Models.Contact = Backbone.Model.extend({
validate: function(attrs) {
if( !attrs.first_name ||
!attrs.last_name ||
!attrs.email_address) {
alert('Fill the missing fields');
}
}
});
// Collection
App.Collections.Contacts = Backbone.Collection.extend({
model: App.Models.Contact,
url : 'index.php/ContactsController/contacts'
});
// Global View
App.Views.App = Backbone.View.extend({
initialize: function(){
vent.on('contact:edit',this.editContact,this);
//console.log(this.collection.toJSON());
App.addContactView = new App.Views.AddContact({collection: App.Contacts});
App.allContactsView = new App.Views.Contacts({collection: App.Contacts});
$('#allcontacts').append(App.allContactsView.el);
}
});
// Add Contact View
App.Views.AddContact = Backbone.View.extend({
el: '#addcontact',
initialize: function(){
this.first_name = $('#first_name');
this.last_name = $('#last_name');
this.email_address = $('#email_address');
this.description = $('#description');
//this will fix it
this.collection.on("change", this.render , this);
},
events: {
'submit' : 'addContact'
},
addContact: function(e){
e.preventDefault();
this.collection.create({
first_name: this.first_name.val(), // <===== same as $this.el.find('#first_name')
last_name: this.last_name.val(),
email_address: this.email_address.val(),
description: this.description.val()
},{wait: true});
this.clearForm();
},
clearForm: function(){
this.first_name.val('');
this.last_name.val('');
this.email_address.val('');
this.description.val('');
}
});
// All Contacts Views
App.Views.Contacts = Backbone.View.extend({
tagName: 'tbody',
initialize: function(){
this.collection.on('add',this.addOne,this);
this.render();
},
render: function(){
this.collection.each(this.addOne,this);
//console.log(this.el);
return this;
},
addOne: function(contact){
var ContactView = new App.Views.Contact({model: contact});
//console.log(ContactView.render().el);
this.$el.append(ContactView.render().el);
}
});
// A view for a single View
App.Views.Contact = Backbone.View.extend({
tagName: 'tr',
template: template('allContactsTemplate'),
initialize: function(){
this.model.on('change',this.render,this);
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
})();

Backbone collection view url firing twice

So my application below is actually firing "FIRE!" in the console twice on page load. Not sure why backbone is firing the url function twice when I am only seeing the one fetch being made. Any ideas as to why this might be causing it to fire twice?
window.ScheduleApp = {
Models: {},
Collections: {},
Views: {}
};
window.template = function(id) {
return _.template($('#' + id).html());
};
//Define the Game Model.
ScheduleApp.Game = Backbone.Model.extend({
initialize: function() {
this.gameId = this.get('Id');
this.gameTime = this.get('Time');
}
});
//Define the Games Collection that contains Game Models.
ScheduleApp.Games = Backbone.Collection.extend({
model: ScheduleApp.Game
});
//Define the Day Model.
ScheduleApp.Day = Backbone.Model.extend({
initialize: function() {
this.games = new ScheduleApp.Games(this.get('Games'));
this.games.parent = this;
this.gameDayGDT = this.get('GeneratedDateTime');
this.gameDayDate = this.get('Date');
}
});
//Define the Days Collection that contains the Day Models.
ScheduleApp.Days = Backbone.Collection.extend({
model: ScheduleApp.Day,
url: function() {
console.log('FIRE!');
return '/js/test.json'
},
parse: function(data) {
var parsedSchedule = JSON.parse('[' + data.STUFF + ']');
return parsedSchedule;
}
});
ScheduleApp.DayCollectionView = Backbone.View.extend({
el: '.container', //Container where the views get rendered to.
initialize: function() {
this.listenTo(this.collection, 'reset', this.render);
},
render: function(event) {
if (this.collection.length === 0) {
$('.container-hidden').show();
}
//Cycle through collection of each day.
this.collection.each(function(day) {
var dayView = new ScheduleApp.DayView({
model: day
});
this.$el.append(dayView.render().el);
}, this);
return this;
}
});
ScheduleApp.DayView = Backbone.View.extend({
tagName: 'div',
className: 'game-date',
template: _.template($("#gameSchedule").html(), this.model),
initialize: function() {
this.listenTo(this.model, "reset", this.render);
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
var daysList = new ScheduleApp.Days();
daysList.fetch({
reset: true,
update: true,
cache: false,
success: function(collection, response) {
//console.log(collection);
},
error: function(model, resp) {
// console.log('error arguments: ', arguments);
// console.log("error retrieving model");
}
});
//create new collection view.
var daysCollectionView = new ScheduleApp.DayCollectionView({
collection: daysList
});
All models belonging to a collection build their URLs based on the collection URL, as stated here. My guess would be that your collection is calling the method once, then your model / models place the second call, in order to build the model URL.
Then again, this method seems pretty harmless to me: it's just a getter. I'd rather place the console.log call in the Collection#parse or Model#initializer methods, and count how many times it gets invoked there.

this.collection.each doesn't iterate

I am trying to understand Backbone and tried to create some small REST API fronted, but can not get View to work.
fetch() returns valid JSON array of three elements. And this.collection.models is not empty (typeof object - []) - it has tree child object elements in it. But each iteration doesn't fire.
When check if collection.models exists with console.log(this.collection.models); it looks like all is right:
I would be thankful for any advice!
var Account = Backbone.Model.extend({});
var AccountsCollection = Backbone.Collection.extend({
model: Account,
url: 'api/v1/accounts',
initialize: function () {
this.fetch();
}
});
var AccountsView = Backbone.View.extend({
render: function() {
// Check if there is something
console.log(this.collection.models);
// This doesn't work
_.each(this.collection.models, function(model) {
console.log(model);
});
// Neither this
this.collection.each(function(model) {
console.log(model);
});
}
});
var a = new AccountsView({collection: new AccountsCollection()});
a.render();
First option
var AccountsCollection = Backbone.Collection.extend({
model: Account,
url: 'api/v1/accounts'
});
var AccountsView = Backbone.View.extend({
render: function() { /**/ }
});
var collection = new AccountsCollection();
var view = new AccountsView({collection:collection});
collection.fetch().done(function () {
// collection has been fetched
view.render();
});
Second option
var AccountsCollection = Backbone.Collection.extend({
model: Account,
url: 'api/v1/accounts'
});
var AccountsView = Backbone.View.extend({
initialize: function() {
this.listenTo(this.collection, 'sync', this.render);
},
render: function() { /**/ }
});
var collection = new AccountsCollection();
var view = new AccountsView({collection:collection});
Third option
var AccountsCollection = Backbone.Collection.extend({
model: Account,
url: 'api/v1/accounts',
initialize: function () {
this.deferred = this.fetch();
}
});
var AccountsView = Backbone.View.extend({
initialize: function() {
this.collection.deferred.done(_.bind(this.render, this));
},
render: function() { /**/ }
});
var collection = new AccountsCollection();
var view = new AccountsView({collection:collection});

Bootstrapping data in backbone.js?

I've manage to put together the below code through various examples, which seems to work okay, but it doesn't seem to preload my data, can anyone please tell me what I'm missing?
App = (function(Backbone, _){
var Note = Backbone.Model.extend(
{
defaults:
{
part1: 'hello',
part2: 'world'
}
});
var TableList = Backbone.Collection.extend({
model: Note
});
var ListRow = Backbone.View.extend(
{
tagName: 'li',
initialize: function()
{
_.bindAll(this, 'render');
},
render: function()
{
$(this.el).html('<span>'+this.model.get('part1')+' '+this.model.get('part2')+'</span>');
return this;
}
});
var ListView = Backbone.View.extend(
{
el: $('#layout_content'),
events:
{
'click button#add': 'addItem'
},
initialize: function()
{
_.bindAll(this, 'render', 'addItem', 'appendItem');
this.collection = new TableList();
this.collection.bind('add', this.appendItem);
this.counter = 0;
this.render();
},
render: function()
{
var self = this;
$(this.el).append("<button id='add'>Add list item</button>");
$(this.el).append("<ul></ul>");
_(this.collection.models).each(function(item){ // in case collection is not empty
self.appendItem(item);
}, this);
},
addItem: function()
{
this.counter++;
var note = new Note();
note.set({part2: note.get('part2') + this.counter});
this.collection.add(note);
},
appendItem: function(item)
{
var listRow = new ListRow({
model: item
});
$('ul', this.el).append(listRow.render().el);
}
});
var app = function(initialModels)
{
this.start = function()
{
this.tableList = new TableList();
this.listView = new ListView({collection: this.tableList});
this.tableList.reset(initialModels);
};
};
return app;
})(Backbone, _);
then init the app with:
<script language="javascript">
var app = new App([{"id":"95","note_title":"can we find the title"},{"id":"93","note_title":"some title"}]);
app.start();
</script>
okay, there are a few issues with your code,
there are 2 issues in your start method,
a) you throw away your collection
this.start = function()
{
this.tableList = new TableList();
this.listView = new ListView({collection: this.tableList});
this.tableList.reset(initialModels);
};
and then in intialize is where you overwrite the collection you pass along
initialize: function()
{
_.bindAll(this, 'render', 'addItem', 'appendItem');
this.collection = new TableList(); // this one gets overwritten, remove this line
}
b) you trigger a collection reset with the models you want to populate it with, but don't listen to an event, either add a listener like this:
this.collection.bind('reset', this.appendAllItems, this);
or create your collection like this:
this.start = function()
{
this.tableList = new TableList(initialModels);
this.listView = new ListView({collection: this.tableList});
};

Categories