Backbone - cannot traverse through object properties - json

I'm trying to traverse through the properties of a json file. You can see my code in http://jsfiddle.net/gerlstar/qRV7k/. In line 38, it should return the values of "name" and "age" in the console. Anyone know what im doing wrong?
var app = {};
app.model2 = Backbone.Model.extend({
defaults: {
age: '',
name: ''
}
});
app.collec = Backbone.Collection.extend({
model: app.model2,
url: 'http://echo.jsontest.com/name/betty/age/22',
parse: function (response) {
return response;
},
initialize: function () {
console.info("init ...");
this.fetch({
success: function (obj, s, jqxhr) {
// console.log(s);
},
error: function (funds) {
console.error("Error in fetch in collec");
}
});
}
});
app.model_with_collec = Backbone.Model.extend({
initialize: function(){
//console.info(this);
this.set({
my_kids: new app.collec()
});
var mo = this.get('my_kids').models;
console.log(mo);
console.log(mo.attributes);//undefined is returned
}
});
new app.model_with_collec();

If you run your code like this it will be executed sequentially and will reach the console.log before the server even respond to the rest call. So it's normal that it prints undefined.
Here the code that will print what you want :
<!DOCTYPE html>
<html>
<head>
<script src="jquery.js"></script>
<script src="underscore.js"></script>
<script src="backbone.js"></script>
<!-- /inladen bower_components -->
<script>
var app = {};
app.model2 = Backbone.Model.extend({
defaults: {
age: '',
name: ''
}
});
app.collec = Backbone.Collection.extend({
model: app.model2,
url: 'http://echo.jsontest.com/name/betty/age/22',
parse: function(response) {
return response;
},
initialize: function() {
console.info("init ...");
this.fetch({
success: function(obj, s, jqxhr) {
// console.log(s);
},
error: function(funds) {
console.error("Error in fetch in collec");
}
});
}
});
app.model_with_collec = Backbone.Model.extend({
initialize: function() {
//console.info(this);
this.set({
my_kids: new app.collec()
});
this.get('my_kids').bind('reset', this.logAttributes, this);
},
logAttributes: function() {
var mo = this.get('my_kids').models;
console.log(mo);
console.log(mo[0].attributes);
}
});
new app.model_with_collec();
</script>
</head>
</html>

Related

How to Read & Update the data in JSON using AngularJs

I am new to Angular js I don't no how to get & Update the value using JSON. Still I tried to get the data from JSON.
But it was not working here is the code.
{
$http.get('json/data.json').success (function(data){
$scope.myData = data;
});
}
Here is the Fiddle Link
Regards
Mahadevan
I would recommend you to read about Angularjs Resource in this link
Then create a service factory which is the best way to ensure re-usability of code: Change the urls to your url and Id is an example for passing parameters.
var app = angular.module('plunker', ['ngResource']);
app.factory('resourceBase', function($resource) {
return {
getData: function() {
return $resource('http://dsd:8080/getdata(:Id)', {
Id: '#id'
});
},
postData: function() {
return $resource('http://dsd:8080/postdata');
},
updataData: function() {
return $resource('http://dsd:8080/postdata(:Id)', {
Id: '#id'
}, {
"update": {
method: "PUT"
}
});
}
}
});
Notice that I included 'ngResource' in angular.module
Then in controller you just use these services
app.controller("MainCtrl", ['$scope', 'resourceBase',
function($scope, resourceBase) {
$scope.name = 'World';
$scope.Id = 1;
$scope.GetData = function() {
resourceBase.getData().get({
Id: $scope.Id
})
.$promise.then(
function(response) {
alert(response);
},
function(error) {
console.log("It was broken !");
alert("Change Get URL to your one");
});
}
$scope.PostData = function() {
resourceBase.postData().save($scope.Id)
.$promise.then(
function(response) {
console.log("Posted");
},
function(error) {
console.log(" Not Posted");
alert("Change Get URL to your one");
});
}
$scope.UpdateData = function() {
resourceBase.updataData().update({
Id: $scope.Id
}, $scope.Id)
.$promise.then(
function(response) {
console.log("Uddated");
},
function(error) {
console.log(" Not Uddated");
alert("Change Get URL to your one");
});
}
}
]);
Here is Plunker Link

BackboneJs fetch() Json to display on View

I am trying to use backbonejs to fetch() JSON data that sent from server to display it in a view. But it doesn't work.
Here is my backbonejs
$(function () {
var Service = Backbone.Model.extend({
url: "/api/album/1",
defaults: {
id: '1',
title: 'abc',
article: 'abc'
},
parse: function (response) {
return response.data;
}
});
// Create a collection of services
var ServiceList = Backbone.Collection.extend({
// Will hold objects of the Service model
url: "/api/album/1",
model: Service
});
var ServiceView = Backbone.View.extend({
tagName: 'li',
events: {
'click': 'toggleService'
},
initialize: function () {
this.listenTo(this.model, 'change', this.render);
},
render: function () {
this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('artist') + '</span>');
this.$('input').prop('checked', this.model.get('checked'));
return this;
},
toggleService: function () {
this.model.toggle();
}
});
var App = Backbone.View.extend({
model: Service,
el: $('#main'),
initialize: function () {
this.model = new ServiceList();
this.model.fetch();
this.list = $('#services');
this.model.each(function (service) {
var view = new ServiceView({model: service});
this.list.append(view.render().el);
}, this);
},
render: function () {
return this;
}
});
new App();
});
Here is my JSON
{"data":{"id":"1","artist":"Gotye","title":"Making Mirrors"}}
Please ignore my bad naming convention in the backbonejs, i am trying to make it work
Try this
var App = Backbone.View.extend({
el: $('#main'),
initialize: function() {
var serviceList = new ServiceList(),
// if you don't have #services in html
//services = $(this.el).html('<div id="services"></div>'),
services = $(this.el).find('#services'),
serviceView;
serviceList.fetch({
success: function(collection) {
collection.each(function(model) {
serviceView = new ServiceView({
model: model
});
services.append(serviceView.render().el);
});
}
});
},
render: function() {
return this;
}
});
DEMO: http://jsbin.com/hiziqi/1/ in this demo I changed url to remote server

Unable to show data in ng-repeat using factory

I have created a factory and making $HTTP request.I have used ng-repeat to show data.Getting data from factory and adding it to $scope variable in controller is unable to show data.The Code is as mentioned below.
I used console.log to get the json returned and it is as mentioned below
JSON:
[{"searchName":"this is test Job","id":"2"},{"searchName":"Job new","id":"1"}]
Angular JS Code:
<script type="text/javascript">
var formApp = angular.module("saveSearch",[]);
formApp.controller("saveSearchController",function($scope,saveServiceSearch)
{
saveServiceSearch.getLatestSaveSearch().then(function(data){
$scope.saveSearches = data;
});
});
formApp.factory('saveServiceSearch', function($http) {
return {
getLatestSaveSearch: function() {
var url = "/job_search_crud.html?act=gtSearchSv";
return promise = $http.get(url,{cache: false});
promise.success(function(data,status, headers, config){
return $data;
});
promise.error(function(data,status, headers, config){
alert("::Request Failed::");
});
}
};
});
</script>
HTML:
<html>
<body ng-app="formApp">
<div ng-controller="saveSearchController">
<table>
<tr ng-repeat="saveSearch in saveSearches" >
<td>{{saveSearch.searchName}}</td>
</tr>
</table>
</div>
</body>
</html>
Try this using $q
myModule.factory('saveServiceSearch', function($q, $timeout, $http) {
var getLatestSaveSearch = function() {
var deferred = $q.defer();
var url = "/job_search_crud.html?act=gtSearchSv";
var data = $http.get(url,{cache: false});
$timeout(function() {
deferred.resolve(data);
}, 2000);
return deferred.promise;
};
return {
getLatestSaveSearch: getLatestSaveSearch
};
});
Edit:
<script type="text/javascript">
var formApp = angular.module("saveSearch",[]);
formApp.controller("saveSearchController",function($scope,saveServiceSearch)
{
saveServiceSearch.getLatestSaveSearch().then(function(data){
$scope.saveSearches = data;
});
});
formApp.factory('saveServiceSearch', function($http) {
return {
getLatestSaveSearch: function() {
var url = "/job_search_crud.html?act=gtSearchSv";
return $http.get(url,{cache: false});
}
}});
</script>

How to render jsonp fetched in BackboneJS?

I'm new in BackboneJS, and I can't render information from JSONP. If I put the data into a data.json and I fetch it, the count appears in the console, but when I use JSONP never re-render.
I don't know if is some kind of delay for obtain the data, but the event of "change" and "reset" are not being trigged by the collection to re-render the view.
The code I have is the next:
// Collection
define([
'underscore',
'backbone',
'models/EstablecimientoModel'],function(_, Backbone, EstablecimientoModel){
var EstablecimientoCollection = Backbone.Collection.extend({
model: EstablecimientoModel,
initialize: function(models, options) {
console.log("Establecimiento initialize");
},
url: function() {
return '../js/establecimientos.json';
//return 'http://localhost:3000/establecimiento';
},
parse: function(data) {
console.log("End of loading data " + JSON.stringify(data) + " datos");
return data;
},
});
return EstablecimientoCollection;
});
// Router
define([
'jquery',
'underscore',
'backbone',
'views/establecimiento/EstablecimientoView',
'jqm'
], function($, _, Backbone,EstablecimientoView) {
'use strict';
var Router = Backbone.Router.extend({
//definition of routes
routes: {
'nearMe' : 'nearMe',
},
nearMe: function(actions) {
var estaColl = new EstablecimientoCollection();
var establecimientoView = new EstablecimientoView({ collection: estaColl });
//estaColl.fetch();
//establecimientoView.render();
this.changePage(establecimientoView);
},
init: true,
changePage: function(view) {
//add the attribute data-role="page" for each view's div
$(view.el).attr('data-role','page');
view.render();
// append to the DOM
$('body').append($(view.el));
var transition = $.mobile.defaultPageTransition;
if(this.firstPage) {
transition = 'none';
this.firstPage = false;
}
// Remove page from DOM when it’s being replaced
$('div[data-role="page"]').on('pagehide', function (event, ui) {
$(this).remove();
});
$.mobile.changePage($(view.el), { transition: transition, changeHash: false });
} // end of changePage()
});
return Router;
});
// View
define([
'jquery',
'underscore',
'backbone',
'collections/EstablecimientoCollection',
'text!templates/establecimiento/establecimientoTemplate.html'
],function($, _, Backbone, EstablecimientoCollection, establecimientoTemplate) {
var EstablecimientoView = Backbone.View.extend({
initialize: function() {
var self = this;
_.bindAll(this,"render");
this.collection.on("change",self.render);
this.collection.fetch({ dataType: 'jsonp', success: function(){ self.render() }});
}, //end of initialize()
template: _.template(establecimientoTemplate),
render: function(eventName) {
console.log("render");
console.log(this.collection.length);
return this;
}, //end of render()
});
return EstablecimientoView;
});
When you fetch your data, make sure you're setting the dataType for your fetch call. Fetch is wrapping a jQuery/Zepto ajax call, so you'll need to set the same parameters you would with those.
this.collection.fetch({
reset: true,
dataType: 'jsonp',
success: function () {
// do stuff
}
});
Also, I'd have your view listen for the events published by the collection rather than calling the view's render directly from the fetch's success callback.

Backbonejs add to collection only if fetch data different

I am writing a small app that calls a json request that has data about a track that is playing for a music player. Every 2-3 minutes that track on the json request changes. I am trying to get backbone to only fire and add another model to my collection if the previous entry called is different. Here is my code so far, however it keeps rendering the same data
// Model: Track
//
//
window.Track = Backbone.Model.extend({});
// Collection: Tracks
//
//
window.Tracks = Backbone.Collection.extend({
model: Track,
url: "api/nowplaying/1.json",
parse: function (response) {
return response.response.body;
}
});
// View: MetaDataView
//
//
window.MetaDataView = Backbone.View.extend({
template: "#metadata-template",
tagName: 'li',
className: 'metadata',
initialize: function() {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.initializeTemplate();
},
initializeTemplate: function() {
this.template = _.template($(this.template).html());
},
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
// View: MetaDataLibraryView
//
//
window.MetaDataLibraryView = Backbone.View.extend({
tagName: 'section',
className: 'metadata-library',
initialize: function() {
_.bindAll(this, 'render', 'startup', 'renderNew');
this.template = _.template($('#metadata-library-template').html());
//this.collection.bind('reset', this.render);
this.collection.on('add', this.renderNew, this);
this.startup();
},
startup: function() {
var e = this;
window.setInterval(function () {
console.log('fetching');
e.collection.fetch({update: true, remove:false, add: true});
}, 2000);
},
renderNew: function(newModel) {
var collection = this.collection;
$metadata = this.$(".metadata-library");
var view = new MetaDataView({ model: newModel, collection: collection });
$metadata.append(view.render().el);
return this;
},
render: function() {
var $metadata,
collection = this.collection;
$(this.el).html(this.template({}));
$metadata = this.$(".metadata-library");
this.collection.each(function(schedule) {
var view = new MetaDataView({ model: schedule,
collection: collection });
$metadata.append(view.render().el);
});
return this;
}
});
I have found posts on stackoverflow talking about the possibility of using collection fetch options like {update: true, remove:false, add: true}. How would I get the data to be rendered only if the model changes that's being fetch?
Something like this should work
startup: function() {
window.setInterval(function () {
console.log('fetching');
var track = new Track();
track.fetch()
.done(function() {
if(!this.isSamePrevTrack(track)) {
e.collection.add(track);
}
}.bind(this));
}.bind(this), 2000);
},
isSamePrevTrack: function(track) {
if(!this.prevTrack) {
this.prevTrack = track;
return false;
}
// Do some test to see if the track is the same
// ie. return this.prevTrack.get('id') === track.get('id');
});