Backbone remove from collection not working - backbone.js

var Wine = Backbone.Model.extend({
winename: "Charles Shaw"
})
var Wines = Backbone.Collection.extend({
Model: Wine
})
var divElement = Backbone.View.extend({
initialize: function () {
this.render();
},
tagName: "ul",
render: function () {
$("#div1").empty();
$("#div1").append("<ul id='ulList'></ul>"),
wines.each(function (model) {
$("#ulList").append("<li>" + model.winename + "</li>");
});
return this;
}
});
var wine1 = new Wine();
wine1.winename = "wine1";
var wines = new Wines();
wines.add(wine1);
var wine2 = new Wine();
wine2.winename = "wine2";
wines.add(wine2);
function changewinename(model, winename) {
this.winename = winename;
}
var d = new divElement(wines);
wines.on("add", addwinename);
wines.on("remove", removewinename);
function addwinename(model, winename) {
d.initialize();
}
function removewinename(model, winename) {
d.initialize();
}
function AddWine() {
var winename = $("#wineName").val();
var wineFromUI = new Wine();
wineFromUI.winename = winename;
wines.add(wineFromUI);
$("#wineName").val("");
}
function changewinename(model, winename) {
this.winename = winename;
}
function RemoveWine() {
var wineValue = $("#wineName").val();
var wine1 = new Wine();
wine1.on({ "change:winename": changewinename });
wine1.set({ winename: wineValue });
alert(wine1.winename);
wines.remove(wine1);
$("#wineName").val("");
}
Collection remove for a model isn't working. Add works fine.

you need to add a function inside your collection like this:
var Wines = Backbone.Collection.extend({
Model: Wine,
removeElement: function(elements, options) {
return this.remove(elements, options);
}
})
and call it like this in your view:
wines.removeElement(wine1);

Related

backbone Cannot read property 'push' of undefined

i'm working with Backbone and when I generate the view I have the error Cannot read property 'push' of undefined". The line of the error is "self.subViewsReservas.push(new ReservaView({" in the push.
ReservaCollectionView = Backbone.View.extend({
initialize: function () {
if (Session.get('authenticated') && Session.get('authenticated') !== false) {
this.paginacionVista = new PaginacionReservasView({
collection: this.collection,
el: '.paginacionReservas',
reservasPagina: 5,
});
this.buscadorVista = new BuscadorView({
el: 'div.buscador-reservas',
//Pasamos la colección oficinas ya que hará las veces del conjunto de oficinas retornadas por el servidor
collection: new OficinasCollection(oficinas),
});
}
else {
}
},
render: function () {
var self = this;
this.template = _.template($('#divReservaTpl').html(), {});
self.$('.contenedor-reservas').empty();
self.collection.each(function (reserva, index) {
self.$('.contenedor-reservas').append(self.template({'data': reserva.toJSON()}));
});
this.collection.each(function (reserva, index) {
this.subViewsReservas = [];
self.subViewsReservas.push(new ReservaView({
el: '#' + reserva.get('Idreserva'),
model: reserva
}));
});
this.collection.each(function (reserva, index) {
//Limite de la paginacion 5 limite arbitrario
if (index < 5) {
//Lo Marcamos como visible y actualiazamos la paginación
self.collection.get(reserva.get('Idreserva')).set({'Visibilidad': true});
}
});
this.paginacionVista.render();
return this;
},
});
AppView = Backbone.View.extend({
initialize : function(){
var self = this;
self.usu = new UsuarioModel();
self.usu.fetch({
success: function (model){
Session.fetch({
success : function (){
Session.set('nombre',model.get('Nombre'));
Session.set('apellidos',model.get('Apellidos'));
Session.set('puntos_club',model.get('Puntosclub'));
self.render();
}
});
self.sideBar = new SideBarView({
el : '.sidebar',
model: model
});
self.sideBar.markOption('mis-reservas');
AppView = Backbone.View.extend({
initialize : function(){
var self = this;
self.usu = new UsuarioModel();
self.usu.fetch({
success: function (model){
Session.fetch({
success : function (){
Session.set('nombre',model.get('Nombre'));
Session.set('apellidos',model.get('Apellidos'));
Session.set('puntos_club',model.get('Puntosclub'));
self.render();
}
});
self.sideBar = new SideBarView({
el : '.sidebar',
model: model
});
self.sideBar.markOption('mis-reservas');
},
error : function (){
document.location = '/mygoldcar/login';
}
});
this.listenTo(Session, 'change', self.update);
},
render : function(){
var self = this;
var reservas = new ReservasCollection();
reservas.fetch({
success: function (collection){
if ( typeof collection.models[0].get('error') == 'undefined' || !collection.models[0].get('error')) {
var listRes = new ReservaCollectionView({
el : '.reservas-list',
collection: collection
});
listRes.render();
var popoverModel = new Popover();
popoverModel.setData(collection.models[0].get('kilometraje_ilimitado'), collection.models[0].get('duracion'));
self.popover = new PopoverView({
el: 'body',
model: popoverModel
});
self.popover.establecerPopover();
}
else document.location = '/mygoldcar' + self.urlLang(lang) + '/mi-cuenta/#msg/1';
},
error: function () {
document.location = '/mygoldcar' + self.urlLang(lang) + '/mi-cuenta/#msg/1';
}
});
},
update: function() {
var self = this;
self.sideBar.update(Session.get('nombre'),Session.get('apellidos'),Session.get('puntos_club'));
self.$el.find('.nombre-usuario').text(Session.get('nombre'));
},
updatePoints: function() {
var self = this;
self.usu.fetch({
success: function (model){
Session.set('puntos_club',model.get('Puntosclub'));
}
});
}
}); },
error : function (){
document.location = '/mygoldcar/login';
}
});
this.listenTo(Session, 'change', self.update);
},
render : function(){
var self = this;
var reservas = new ReservasCollection();
reservas.fetch({
success: function (collection){
if ( typeof collection.models[0].get('error') == 'undefined' || !collection.models[0].get('error')) {
var listRes = new ReservaCollectionView({
el : '.reservas-list',
collection: collection
});
listRes.render();
var popoverModel = new Popover();
popoverModel.setData(collection.models[0].get('kilometraje_ilimitado'), collection.models[0].get('duracion'));
self.popover = new PopoverView({
el: 'body',
model: popoverModel
});
self.popover.establecerPopover();
}
else document.location = '/mygoldcar' + self.urlLang(lang) + '/mi-cuenta/#msg/1';
},
error: function () {
document.location = '/mygoldcar' + self.urlLang(lang) + '/mi-cuenta/#msg/1';
}
});
},
update: function() {
var self = this;
self.sideBar.update(Session.get('nombre'),Session.get('apellidos'),Session.get('puntos_club'));
self.$el.find('.nombre-usuario').text(Session.get('nombre'));
},
updatePoints: function() {
var self = this;
self.usu.fetch({
success: function (model){
Session.set('puntos_club',model.get('Puntosclub'));
}
});
}
});
Inside collection.each, this points to the collection. So the property subViewsReservas is added to it, not the view instance. When you try to access it like self.subViewsReservas.push, self points to the view instance, which doesn't have subViewsReservas property, hence the error.
Initializing an array inside each like you're doing isn't doing much since it'll be reset with each invocation of the callback.
You should be initializing it in the initialize method, which is the right place to initialize things, where this will correctly point to the view instance as shown below
initialize: function () {
this.subViewsReservas = [];
}
For some reason if you want the collection to reset everytime, you can change the context to view by passing it as second argument to each like:
this.collection.each(function (reserva, index) {
this.subViewsReservas = [];
self.subViewsReservas.push(new ReservaView({
el: '#' + reserva.get('Idreserva'),
model: reserva
}));
}, self); // <--- makes view the context of callback,
// both 'self' and 'this' will refer to view

Backbone Collections Undefined

In my database, I am simply trying to grab every object from my "countries" array, however when I run it, the console tells me that my collections is undefined.
index.js
var Backbone = require('backbone')
var App = require('./app.js')
var countryCollection = require('./collections/countries');
var countryModel = require('./models/country')
var countryView = require('./views/country-bio');
App.Views.CountryBio = new CountryBioView;
App.Router = Backbone.Router.extend({
routes: {
'bio.html(/)': 'index',
'*actions': 'defaultRoute'
},
index: function() {
console.log(countryCollection)
console.log('this works')
},
defaultRoute: function() {
console.log("404 Page Not Found")
}
})
App.Router = new App.Router;
Backbone.history.start();
Collections
var Backbone = require('backbone');
var App = require('../app');
var Country = require('../models/country');**strong text**
var CountryCollection = Backbone.Collection.extend({
url: 'http://localhost:3000/countries',
model: Country
});
App.Collections.country = new CountryCollection;
module.exports = App.Collections.country;
Models
var Backbone = require('backbone');
var App = require('../app');
App.Models.Country = Backbone.Model.extend({
url: function() {
return 'http://localhost:3000/countries';
}
});
module.exports = App.Models.Country;
Views
var $ = require('jquery');
var Backbone = require('backbone');
var countryBioTemplate = require('../templates/countryBio.hbs');
var App = require('../app');
var CountryBio = Backbone.View.extend({
el: $('main'),
collection: App.Collections.country,
render: function () {
var _this = this;
var countryCollection = this.collection;
console.log(countryCollection)
// Fetch Collection from Server
// countryCollection.fetch().done(function (country) {
// _this.$el.html(countryBioTemplate(country));
// });
}
});
module.exports = CountryBio;

backbone model and collection

help me understand why the code is not working properly
my code:
var Link = Backbone.Model.extend({
defaults : {
groups: []
}
});
var LinkCollection = Backbone.Collection.extend({
model:Link,
url: 'item.json'
});
var Group = Backbone.Model.extend({
defaults: {
links: []
},
initialize : function() {
this.on("all" , function(event) {
console.log(event);
});
this.on("change:links" , function() {
console.log(this.get("links").length , this.id);
})
},
setLink: function(link) {
var links = this.get("links");
links.push(link);
this.set("links" , links);
this.trigger("change:links" , this);
},
removeLink : function(link) {
var links = this.get("links") , index = links.indexOf(link);
links.splice(index , 1);
this.set("links" , links);
this.trigger("change:links" , this);
}
});
var GroupCollection = Backbone.Collection.extend({
model:Group,
url: 'group.json',
setLinks : function(links) {
var self = this;
this.links = links;
this.links.on('all' , function(event) {
console.log(event);
});
this.links.on('add' , self.setLink , this);
this.links.on('remove' , this.removeLink , this);
this.links.on('reset' , this.resetLinks , this);
},
setLink : function(link) {
var self = this , test = false;
if(self.length ) {
link.get('groups').forEach(function(groupId) {
var group = self.get(groupId);
console.log(group , groupId);
if( group ) {
test = true;
group.setLink(link);
}
});
if(!test) {
self.get("notInGroup").setLink(link);
}
self.get("allObjects").setLink(link);
}
},
resetLinks : function() {
this.links.each(this.setLink);
},
initialize: function() {
var self = this;
this.on('reset' , self.resetLinks , this);
},
removeLink: function(link) {
var self = this;
link.get('groups').forEach(function(groupId) {
var group = self.get(groupId);
if(group) {
group.removeLink(link);
}
})
}
});
var LinkView = Backbone.View.extend({
tagName: 'li',
className : 'list-item',
template: _.template($("#ListView").html()),
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this
}
});
var GroupView = Backbone.View.extend({
tagName : 'li',
className: 'group-list ',
template: _.template($("#GroupView").html()),
initialize: function() {
this.model.on('remove', function() {
console.log('remove');
});
this.model.on('reset' , function() {
console.log('reset');
});
this.model.on('destroy' , function() {
console.log('destroy')
});
},
render: function() {
var model = this.model.toJSON();
this.$el.html(this.template(model));
this.renderLinks(this.model);
this.model.on('change:links' , this.renderLinks.bind(this));
return this;
},
renderLinks : function(group) {
var self = this;
self.$el.find("ul").empty();
group.get("links").forEach(function(link) {
var view = new LinkView({model: link});
self.$el.find("ul").append(view.render().el);
});
}
})
var App = Backbone.View.extend({
el: $('#content'),
initialize: function() {
this.links = new LinkCollection();
this.groups = new GroupCollection();
this.groups.setLinks(this.links);
this.groups.bind('add', this.addGroup, this);
this.groups.bind('reset', this.addGroups, this);
this.links.fetch();
this.groups.fetch({reset: true});
return this;
},
render: function() {
this.$el.html($('#GroupListView').html())
},
addGroup: function(model) {
var view = new GroupView({model: model});
this.$("ul.group-list").append(view.render().el);
},
addGroups: function() {
this.groups.each(this.addGroup)
}
})
$(function() {
var app = new App();
app.render();
})
working example http://plnkr.co/edit/40CCIq0jt2AdmGD61uAn
but instead of the expected list of groups I get incorrect group
this list i tried to get:
All Objects
First
Second
Third
Fourth
Fifth
FirstGroup
First
Third
SecondGroup
Third
Fourth
NotInGroup
Second
Fifth
upd: Groups and Links can come at different times, so the order of their receipt is not critical. the problem is that for some reason the models groups added extra value, which should not be there
Screenshot added. Please look at the highlighted change

Backbone/Marionette ItemView not rendering on model change

Already a couple of hours struggle trying to solve this...
Although the model gets fetched correctly and I can verify it as the view gets informed of the model's 'change' event, it just does not render.
At startup, the default model data ('Test Project'), is correctly displayed in the view, but after the model is refreshed, the view is not refreshed.
I tried to show a new view in the layout after model refresh but it did not change much...
Any idea or opinion about this ?
App.Project = function () {
var Project = {};
var ProjectModel = Backbone.Model.extend({
defaults:{
id: 0,
name: "Test Project",
intro: "",
desc: ""
},
initialize: function () {
// Flag fetch status to avoid multiple simultaneous calls
this.loading = false;
var self = this;
App.vent.on("project:display", function (_id) { self.fetchProject(_id); });
},
fetchProject: function (_id) {
if (this.loading)
return true;
this.loading = true;
var self = this;
var id = _id;
this.url = 'data.project_'+id+'.json';
this.fetch({
success: function (_data) {
self.loading = false;
},
error: function () {
self.loading = false;
}
});
}
});
Project.Details = new ProjectModel();
var Layout = Backbone.Marionette.Layout.extend({
template: "#project-layout",
regions: { details: "#project_details" }
});
Project.initializeLayout = function () {
Project.layout = new Layout();
App.content.show(App.Project.layout);
};
App.addInitializer(function () {
App.Project.initializeLayout();
});
Project.display = function () {
App.Project.Views.showDetails(Project.Details);
App.vent.trigger("project:display", 1);
}
return Project;
}();
App.Project.Views = function () {
var Views = {};
var DetailView = Backbone.Marionette.ItemView.extend({
template: "#project-details-template",
tagName: "div",
initialize: function () {
//this.listenTo(this.model, "change", this.render, this);
},
modelEvents: {
'change': "modelChanged"
},
modelChanged: function() {
console.log(this.model);
this.render();
}
});
Views.showDetails = function (_project) {
var projectView = new DetailView({model: _project});
App.Project.layout.details.show(projectView);
};
return Views;
}();
App.ProjectRouting = function () {
var ProjectRouting = {};
ProjectRouting.Router = Backbone.Marionette.AppRouter.extend({
initialize: function (_options) {
this.route('project/', "displayProject", _options.controller.display);
}
});
App.vent.on("project:display", function (_id) {
App.navigate("project/");
});
App.addInitializer(function (_options) {
ProjectRouting.router = new ProjectRouting.Router({
controller: App.Project
});
});
return ProjectRouting;
}();

How to delete a dependent model from the same collection in backbone.js

I have a model which has both navid and subnavid .While destroying a model i need to check in the entire collection , for other models which have navid as same as subnavid of the model i'am trying to delete . Please help me out . Thanks in advance . Heregoes my sample code.
Model:
var Node = Backbone.Model.extend({
defaults: {
NavId: '',
SubNavId: ''.
ItemName:''
} }
Collection:
var NodeCollection = Backbone.Collection.extend({ model:Node }
And i have two view one for the Node(i am building tr) and other for
the collection(I need to build table) var NodeCollectionView =
Backbone.View.extend({
initialize: function (options) {
var self = this; self.collection = new NodeCollection({ NavigationId: options.NavigationId });
self.collection.fetch({
success: function () {
/*I am getting hte proper collection from my restful api and iam able to bind it properly
self.render();
}
});
},
render: function () {
var that = this;
_.each(this.collection.models, function (item) {
that.RenderEachNode(item);
}, this);
},
RenderEachNode: function (item) {
var TempJsonNode = item.toJSON();
var self = this;
var nodeView = new NodeView({
tagName: 'tr',
id: 'NavId_' + TempJsonNode.NavItemId,
model: item
});
} });
var ItemTemplate = ""; ItemTemplate += " <td>"; ItemTemplate += " <a><%= ItemName %></a>"; ItemTemplate +=" </td>"; ItemTemplate
+=" <td>"; ItemTemplate +=" <a href='#' original-title='Delete ' class='tip_north Delete'>X</a>"; ItemTemplate +=" </td> ";
var NavigationItemView = Backbone.View.extend({
template: ItemTemplate,
render: function () {
var self = this;
var tmpl = _.template(this.template);
this.$el.html(tmpl(this.model.toJSON()));
return this;
},
events: {
"click .Delete": "DeleteBtnClick"
},
DeleteBtnClick: function () {
var self = this;
self.model.destroy({
success: function (status, data) {
var RetData = JSON.parse(data);
if (RetData.Status == 'Success') {
$(self.el).remove()
}
},
error: function () {
alert('Error In Deleting The Record');
}
});
return false;
} });
I am able to build the table properly but while destroying a model , i am not figuring out a way to destroy the dependent models.My Api is restricted in such a way that i cannot get a nested json ( if so i would have done with backbone relation). so i need to figure out some way that the other models and views which has the NavId of the model am deleting.
Please help me out.
How about something like:
var NodeView = Backbone.View.extend({
initialize: function() {
//when the model gets destroyed, remove the view
this.listenTo(this.model, 'destroy', this.remove);
},
//..clip
DeleteBtnClick: function () {
var self = this;
var collection = self.model.collection;
var navId = self.model.get('NavId');
self.model.destroy({
success: function (status, data) {
var RetData = JSON.parse(data);
if (RetData.Status == 'Success') {
//if parent was part of a collection
if (collection) {
//find related models
var related = collection.filter(function (model) {
return model.get('SubNavId') === navId;
});
//call destroy for each related model.
var promises = _.invoke(related, 'destroy');
//optional: if you want to do something when all the children
//are destroyed:
$.when.apply($, promises).then(function () {
console.log('all destroyed');
});
}
}
},
error: function () {
console.log(arguments);
alert('Error In Deleting The Record');
}
});
return false;
}
});
Edit: JSFiddle here

Resources