im learning BackboneJs using the documentation and a book called "Beginning backbone".
But I have been stuck at the sorting collections part for hours.
Also tried to research but I find the results complicated =/
I know I have to use the comparator, as shown in the documentation but I don't understand how to apply it to the current code syntax-wise
http://backbonejs.org/#Collection-comparator
var Book = Backbone.Model.extend({
defaults:
{
title: "default title",
author: "default author",
pages: 20
},
comparator: function(item)
{
//sort by title
return item.get('title');
}
});
var book1 = new Book({ title:"Book of wonders",author:"author1",pages:1 });
var book2 = new Book({ title:"Zelda",author:"author2",pages:2 });
var book3 = new Book({ title: "Drake's out", author: "author3",pages:3});
var book4 = new Book({ title: "AutoCad",author: "author4",pages: 4});
var Library = Backbone.Collection.extend({
model: Book
});
var library = new Library([book1,book2]);
library.add([book3,book4]);
library.forEach(function(model){
console.log('Book is called '+model.get("title"));
});
console.log('Library contains '+library.length+' books');
This is a working solution, it will sort everything by title.
to sort it by anything else just change the parameter of the get function inside the comparator function
var Book = Backbone.Model.extend({
defaults:
{
title: "default title",
author: "default author",
pages: 20
}
});
var book1 = new Book({ title:"Book of wonders",author:"author1",pages:1 });
var book2 = new Book({ title:"Zelda",author:"author2",pages:2 });
var book3 = new Book({ title: "Drake's out", author: "author3",pages:3});
var book4 = new Book({ title: "AutoCad",author: "author4",pages: 4});
var Library = Backbone.Collection.extend({
model: Book,
initialize: function()
{
console.log("new collection");
},
comparator: function(a,b)
{
//sort by title
return a.get('title') < b.get('title') ? -1 : 1;
}
});
var library = new Library([book1,book2]);
library.add([book3,book4]);
library.sort();
library.forEach(function(model){
console.log('Book is called '+model.get("title"));
});
console.log('Library contains '+library.length+' books');
Related
I don't know where are the issue I tried to push a new book to my books array and I get this error.
This is the book-edit.component.ts
ngOnInit() {
this.authorsService.authorsChanged.subscribe(
(authors: Author[]) => {
this.authors = authors;
}
);
this.authorsService.getAuthors();
this.bookForm = new FormGroup({
'id': new FormControl(Math.floor(Math.random() * 10000000000)),
'title': new FormControl('new book'),
'author': new FormControl(null),
'description': new FormControl('description'),
'publishYear': new FormControl('1991'),
'image': new FormControl('https://www.reduceimages.com/img/image-after.jpg')
});
}
onSubmit() {
const book = {
id: this.bookForm.value.id,
title: this.bookForm.value.title,
author: this.bookForm.value.author,
description: this.bookForm.value.description,
publishYear: this.bookForm.value.publishYear,
image: this.bookForm.value.image
};
this.booksService.addBook(book);
console.log(book);
}
and this is the function I call from the booksService.ts
addBook(book: Book) {
this.books.unshift(book);
this.booksChanged.next(this.books);
}
For the error log, it seems that this.books is not initialized. Can you initialize books variable in bookservice.ts to empty array like books = []
addBook(book: Book) {
this.books.unshift(book);
this.booksChanged.next(this.books);
}
I'm trying to get some data from the node server, which works fine, but when I try to GET data via the Backbone fetch (or sync), the request fails. I noticed that, for some reason, actual request is wrong: 'GET http://localhost:3000/socket.io/1/' where it should be 'GET http://localhost:3000/cars', since '/cars' is the value of the URL field that Backbone uses by convention for these operations. These are the relevant modules:
var Backbone = require("backbone");
var Car = require('models/car');
var Cars = Backbone.Collection.extend ({
model: Car,
url: '/cars',
// Unselect all Car Cards
resetSelected: function() {
for (var i=1; i<=this.length; ++i) {
var carcard=this.get(i);
carcard.set({"selected": false});
console.log(carcard.attributes.name + ' unselected');
}
},
// Select a specific model from the collection
selectByID: function(id) {
this.resetSelected();
var carcard = this.get(id);
carcard.set({"selected": true});
console.log(carcard.attributes.name + " selected");
return carcard.attributes.id;
}
});
module.exports = Cars;
And a model:
var Backbone = require("backbone");
var Car = Backbone.Model.extend({
defaults: {
year: 2011,
brand: "Brand",
model: "Model",
name: "Car Name",
pictureFle: "img/car.jpg",
kmTraveled: 0,
litresSpent: 0,
selected: false
},
});
module.exports = Car;
I tried to populate the collection like this:
var cars = new Cars();
cars.fetch();
but, as I explained, failed. Any ideas what the problem could be?
I have a Backbone App with 3 model which have nested collections:
Models Structure:
Layout extends Backbone.Model
-> sections: new Sections extends Backbone.Collection
Section extends Backbone.Model
-> rows: new Rows extends Backbone.Collection
Now if I have two section model in layout and I go and add row model to one of the Section.rows collection, it is adding it to both sections.
BTW, I am adding it from a view on an event.
Thanks in Advance.
got a workaround. I could reproduce your workflow by adding defaults property to my models.
like this:
var Section = Backbone.Model.extend({
defaults: {
rows: new Rows
}
});
var Layout = Backbone.Model.extend({
defaults: {
sections: new Sections
}
});
then really, if i add new row to rows to one of my section its appear to adding to all sections rows collection. So i do this (rude example):
var Row = Backbone.Model.extend({
defaults: {
rowData: 0
}
});
var Rows = Backbone.Collection.extend({
model: Row
});
var Section = Backbone.Model.extend({
//defaults: {
// rows: new Rows
//}
});
var Sections = Backbone.Collection.extend({
model: Section
});
var Layout = Backbone.Model.extend({
//defaults: {
// sections: new Sections
//}
});
var LayoutView = Backbone.View.extend({
});
var lView = new LayoutView({ model: new Layout });
lView.model.set('sections',new Sections());
var sections = lView.model.get('sections');
sections.add({id: 1, name: 's1',rows: new Rows() });
sections.add({id: 2, name: 's2',rows: new Rows() })
var rows = sections.get(1).get('rows');
rows.add({id:'r1',rowsData: 10});
console.log(lView.model.toJSON());
#aleha you are right the issue is of the default attribute settings in Model. As they share the same memoery space(javascript: pass by reference not by value ).
So what I did is in the initialize function
initialize: function() {
this.set( 'rows', new Rows() );
}
So, no need to do it like you are doing above:
sections.add({id: 1, name: 's1',rows: new Rows() });
Hence resolved and automate :)
Thanks for the help though.
I asked this before BackboneJS Display multiple collections in one <ul>-Element but I can't get it to work and I'm starting getting really desperate so
how can I merge these 3 collections and display them in the same <ul>?
define(['app','backbone','modules/artistInstagram', 'modules/artistTwitter',
'modules/artistFacebook'
], function (App, Backbone, ArtistInstagram, ArtistTwitter, ArtistFacebook) {
var ArtistSocialMedia = App.module();
ArtistSocialMedia.View = Backbone.View.extend({
tagName: 'ul',
id: 'suptiles',
beforeRender: function(){
var artistinstagramCollection = new ArtistInstagram.ArtistInstagramCollection();
artistinstagramCollection.artist_id = this.artist_id;
this.insertView('.socialMedia', new ArtistInstagram.View({collection: artistinstagramCollection}));
artistinstagramCollection.fetch();
var artisttwitterCollection = new ArtistTwitter.ArtistTwitterCollection();
artisttwitterCollection.artist_id = this.artist_id;
this.insertView('.socialMedia', new ArtistTwitter.View({collection: artisttwitterCollection}));
artisttwitterCollection.fetch();
var artistfacebookCollection = new ArtistFacebook.ArtistFacebookCollection();
artistfacebookCollection.artist_id = this.artist_id;
this.insertView('.socialMedia', new ArtistFacebook.View({collection: artistfacebookCollection}));
artistfacebookCollection.fetch();
}
});
return ArtistSocialMedia;
});
Right now, it clearly creates 3 views but I want to merge them into one collection. Please help!
Thanks in advance...
Don't overthink it - since you're defining an element with dynamic content, it should be its own View. It's an unordered list, so the tag name must be <ul>. All you're doing is filling in the <li>'s, so the template isn't very complicated.
var collection1 = new WhateverCollection();
var collection2 = new WhateverCollection();
var collection3 = new WhateverCollection();
var ListView = Backbone.View.extend({
tagName: 'ul',
render: function(){
// define template
var templateStr = '<% _.each(collection,function(model){ %>\
<li><%- model.name %></li>\
<% }); %>';
// convert to function
var template = _.template(templateStr);
// for learning purposes, render each one individually
var htmlFromFirst = template({ collection: collection1.toJSON() });
var htmlFromSecond = template({ collection: collection2.toJSON() });
var htmlFromThird = template({ collection: collection3.toJSON() });
// set the html
this.$el.html( htmlFromFirst + htmlFromSecond + htmlFromThird );
return this;
}
});
When I make some components in my web page,I found there a so many duplicate codes,for example,in my page I want to make two charts.
THe biggest difference of them is the data store and the title,however they have many same attributes.
I do this by define a new instance of Ext.chart:
var chart1=new Ext.chart.LineChart{config1};
var chart2=new Ext.chart.LineChart{config2};
There are so many same contents in the config1 and config2,is there any ideas to avoid this?
BTW,I have thought the extend mechanism in ext,however I can not get more details about how to use it only from the ext3.2 API.
You can extend config
var config = {
// do you shared config here
}
// and apply any different/extending configs here
var config1 = Ext.apply(config, { title: "Title of config 1" }
var config2 = Ext.apply(config, { title: "Title of config 2" }
var chart1 = new Ext.chart.LineChart(config1);
var chart2 = new Ext.chart.LineChart(config2);
And if you want it even shorter:
var chart1 = new Ext.chart.LineChart(Ext.apply(config, {
title: "Title of config 1"
});
var chart2 = new Ext.chart.LineChart(Ext.apply(config, {
title: "Title of config 2"
});
Edit: With Ext.extend:
Ext.chart.LineChart = Ext.extend(Ext.chart.LineChart, {
// put your shared config in here
});
var chart1 = new Ext.chart.LineChart({
title: "Title of chart 1",
store: new Ext.data.Store({ ... });
});
var chart2 = new Ext.chart.LineChart({
title: "Title of chart 2",
store: new Ext.data.Store({ ... });
});