BackboneCollection.Unshift(NewItem) - not working - backbone.js

i have a Backbone collection and it was hold by a knockback.ObservableCollection and i want to add he new items on the Top just like Array.Shift(NewItem). Is there anyway to do that? i pretty new with backbonejs
this.recentItemList = kb.collectionObservable(recentItems, {
view_model: RecentItemViewModel, sort_attribute: 'modifiedDateTime'
});
var options = {};
var self = this;
var newRecentItem = new recentItem
({
recentId: model.get("id"),
recentName: model.get("description"),
type: "test"
});
options.success = function ()
{
self.recentItems.unshift(newRecentItem);
};
newRecentItem.save({}, options);

Make your viewModel variable a ko.observableArray, and you can then just variableName.unshift(newElement);

Okay, my mistakes.
so i just removed the sort_attribute and it works like a charm.

Related

How to add a ng-model property to a object in the Angular controller

I do not understand why the the uuid and datetime is not binding from my controller to my view. It isn't necessary though, I can add them to the object in the controller. problem is I'm not sure how to do that. I need to add the .dt & .CivilCaseId to the newCivilCase. thanks
//Generate Unique Id
$scope.newCivil = [];
$scope.newCivil.CivilCaseId = uuid2.newuuid();
console.log($scope.newCivil.CivilCaseId);
//Todays Date
$scope.newCivil.dt = new Date();
console.log($scope.newCivil.dt);
//Post Civil Case
$scope.newCivil = new Civil();
$scope.addCivilCase = function () {
$scope.newCivil.$save(function () {
console.log($scope.newCivil); $state.go('home');
});
};
Seems in your first line, you set
$scope.newCivial = [];
But after that, you set
$scope.newCivil = new Civil(); //return object previous 'newCivil' is covered by this statement.
Suggest you to change your code into this:
//Generate Unique Id
$scope.newCivil = new Civil();
$scope.newCivil.CivilCaseId = uuid2.newuuid();
$scope.newCivil.dt = new Date();
console.log($scope.newCivil.dt);
//Post Civil Case
$scope.addCivilCase = function () {
$scope.newCivil.$save(function () {
console.log($scope.newCivil); $state.go('home');
});
};

BackboneJS How to merge collections

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;
}
});

Get properties of a Backbone model starting with certain text using Underscore.js

I have a Backbone Model in which there are certain properties like
test_id
test_name
test_desc
test_score
Now I want to retrieve properties which are starting with "test_".
I tried with code below and its working fine.
var MyModel = Backbone.Model.extend({
getTestProperties: function(str){
// get clone of attributes to iterate over
var testProperties = {};
var attrs = _.clone(this.attributes);
_.each(attrs, function(val, key){
if(key.indexOf(str) == 0){
testProperties[key]= val;
}
}, this);
}
});
But
Is there any other way I can get these properties using underscore methods ?
Thanks
Backbone proxies some methods from Underscore on models that can help you create a more readable _.filter: _.keys and _.pick
You can then simplify your function like this :
var MyModel = Backbone.Model.extend({
getTestProperties: function (str) {
// get the keys you want
var keys = _.filter(this.keys(), function (key) {
return key.indexOf(str) === 0;
});
// and build an object
return this.pick(keys);
}
});
And a demo http://jsfiddle.net/nikoshr/5a63c/
Try something like
var attrs = _.filter(_.keys(_.clone(this.attributes)), function(attr){
return attr.indexOf("text_") === 0;
});

Scoping issue in backbone view

I am in the process of getting a simple drawing view created using Easeljs inside of a Backbonejs view. I am having an issue with scope, in my listener events, for example:
this.stage.addEventListener("stagemousedown", this.handleMouseDown);
I started to started doing this to get around my scope issue
var self = this;
this.stage.addEventListener("stagemousedown", function(){
var foo = self.bar;
});
However, this seems sloppy, especially since the sample code I am porting (http://www.createjs.com/#!/EaselJS/demos/drawing), has nested levels of eventListeners.
SketchView = Backbone.View.extend({
initialize: function(){
this.canvas;
this.stage;
this.drawingCanvas;
this.oldPt;
this.oldMidPt;
this.title;
this.color;
this.stroke;
this.colors;
this.index;
},
beforeRender : function (){
this.template = _.template( tpl.get(this.templateFile) );
},
render: function(eventName) {
$(this.el).html(this.template(this.model));
return this;
},
//add in UI
afterRender : function (){
this.createUI();
},
createUI: function() {
this.canvas = document.getElementById("demoCanvas");
this.index = 0;
this.colors = ["#828b20", "#b0ac31", "#cbc53d", "#fad779", "#f9e4ad", "#faf2db", "#563512", "#9b4a0b", "#d36600", "#fe8a00", "#f9a71f"];
//Create a stage by getting a reference to the canvas
this.stage = new createjs.Stage(this.canvas);
this.stage.autoClear = false;
this.stage.enableDOMEvents(true);
createjs.Touch.enable(this.stage);
createjs.Ticker.setFPS(24);
this.stage.addEventListener("stagemousedown", this.handleMouseDown);
this.stage.addEventListener("stagemouseup", this.handleMouseUp);
this.title = new createjs.Text("Click and Drag to draw", "36px Arial", "#777777");
this.title.x = 300;
this.title.y = 200;
this.stage.addChild(this.title);
this.stage.addChild(this.drawingCanvas);
this.stage.update();
},
handleMouseDown: function (event) {
if (this.stage.contains(this.title)) { this.stage.clear(); this.stage.removeChild(this.title); }
this.color = this.colors[(this.index++)%this.colors.length];
this.stroke = Math.random()*30 + 10 | 0;
this.oldPt = new createjs.Point(this.stage.mouseX, this.stage.mouseY);
this.oldMidPt = this.oldPt;
this.stage.addEventListener("stagemousemove" , this.handleMouseMove);
},
handleMouseMove: function (event) {
var midPt = new createjs.Point(this.oldPt.x + this.stage.mouseX>>1, this.oldPt.y+this.stage.mouseY>>1);
this.drawingCanvas.graphics.clear().setStrokeStyle(this.stroke, 'round', 'round').beginStroke(this.color).moveTo(midPt.x, midPt.y).curveTo(this.oldPt.x, this.oldPt.y, this.oldMidPt.x, this.oldMidPt.y);
this.oldPt.x = this.stage.mouseX;
this.oldPt.y = this.stage.mouseY;
this.oldMidPt.x = midPt.x;
this.oldMidPt.y = midPt.y;
this.stage.update();
},
handleMouseUp: function (event) {
this.stage.removeEventListener("stagemousemove" , this.handleMouseMove);
}
});
An unrelated question, is should I be instantiating my variables in the initialize function? I am still new to Backbone, and trying to figure out best practices.
Backbone requires the Underscore library, and I strongly recommend becoming familiar with it : it has a lot of great stuff. In particular it has a _.bind method that you can use like so:
this.stage.addEventListener("stagemousedown", _(function(){
var foo = this.bar; // "this" will be correct now thanks to bind
}).bind(this);
It also has a related _.bindAll method, which can be used (often inside of an initialize function) to bind an object's methods to it, like so:
initialize: function() {
_(this).bindAll('handleMouseDown'); // handleMouseDown's this will be correct
this.stage.addEventListener("stagemousedown", this.handleMouseDown);
}
However, you can avoid all of this and let Backbone do the binding for you if you just take advantage of its event handling:
Backbone.View.extend({
events: {mousedown: 'handleMouseDown'}
handleMouseDown: function() {
// this will be bound correctly
As for your question about instantiating variables inside initialize, the answer is ... probably, but it's hard to say without knowing your specific context. In general, initialize should do anything that needs to happen when the Collection/Model/View gets created, so if initializing variables falls under that then sure.

passing data to a collection in backbone

So I am trying storing product types from a json file before trying to add them to a collection but am getting some strange results (as in I dont fully understand)
on my router page i setup a variable for cached products as well as product types
cachedProductTypes: null,
productType : {},
products : {},
getProductTypes:
function(callback)
{
if (this.cachedProductTypes !== null) {
return callback(cachedProductTypes);
}
var self = this;
$.getJSON('data/product.json',
function(data)
{
self.cachedProductTypes = data;
callback(data);
}
);
},
parseResponse : function(data) {
result = { prodTypes: [], products: [] };
var type;
var types = data.data.productTypeList;
var product;
var i = types.length;
while (type = types[--i]) {
result.prodTypes.push({
id: type.id,
name: type.name,
longName: type.longName
// etc.
});
while (product = type.productList.pop()) {
product.productTypeId = type.id,
result.products.push(product);
}
};
this.productType = result.prodTypes;
console.log( "dan");
this.products = result.products;
},
showProductTypes:function(){
var self = this;
this.getProductTypes(
function(data)
{
self.parseResponse(data);
var productTypesArray = self.productType;
var productList=new ProductsType(productTypesArray);
var productListView=new ProductListView({collection:productList});
productListView.bind('renderCompleted:ProductsType',self.changePage,self);
productListView.update();
}
);
}
when a user goes to the show product types page it runs the showProductsType function
So I am passing the products type array to my collection
on the collection page
var ProductsType=Backbone.Collection.extend({
model:ProductType,
fetch:function(){
var self=this;
var tmpItem;
//fetch the data using ajax
$.each(this.productTypesArray, function(i,prodType){
tmpItem=new ProductType({id:prodType.id, name:prodType.name, longName:prodType.longName});
console.log(prodType.name);
self.add(tmpItem);
});
self.trigger("fetchCompleted:ProductsType");
}
});
return ProductsType;
now this doesnt work as it this.productTypesArray is undefined if i console.log it.
(how am I supposed to get this?)
I would have thought I need to go through and add each new ProductType.
the strange bit - if I just have the code
var ProductsType=Backbone.Collection.extend({
model:ProductType,
fetch:function(){
var self=this;
var tmpItem;
//fetch the data using ajax
self.trigger("fetchCompleted:ProductsType");
}
});
return ProductsType;
it actually adds the products to the collection? I guess this means I can just pass an array to the collection and do not have to add each productType?
I guess this means I can just pass an array to the collection and do not have to add each productType?
Yes, you can pass an array to the collection's constructor, and it will create the models for you.
As far as your caching code, it looks like the problem is here:
if (this.cachedProductTypes !== null) {
return callback(cachedProductTypes);
}
The callback statement's argument is missing this - should be return callback(this.cachedProductTypes).

Resources