Backbone sometimes load sometimes not - json

I have a Backbone app where I load external Json.
Sometimes I see the image inside the json(url) sometimes not, like the fetch doesn't finish in time.
Json that doesn't load sometimes are amenities (that contains url to image) and image (that contains url to image)
This is my app simplified:
HotelModel = Backbone.Model.extend({
initialize: function() {
// because initialize is called after parse
_.defaults(this, {
amenities: new AmenityCollection(),
image: new ImageCollection()
});
},
parse: function(response) {
if (_.has(response, "image")) {
this.image = new ImageCollection(response.image, {
parse: true
});
delete response.image;
}
if (_.has(response, "amenities")) {
this.amenities = new AmenityCollection(response.amenities, {
parse: true
});
delete response.amenities;
}
return response;
},
toJSON: function() {
var json = _.clone(this.attributes);
json.rooms = this.rooms.toJSON();
return json;
},
addAmenity: function(amenities, options) {
return this.amenities.add(amenities, options);
},
addRoom: function(rooms, options) {
return this.rooms.add(rooms, options);
},
addImage: function(image, options) {
return this.image.add(image, options);
}
});
AmenityModel = Backbone.Model.extend({});
ImageModel = Backbone.Model.extend({});
HotelCollection = Backbone.Collection.extend({
model: HotelModel,
}
});
AmenityCollection = Backbone.Collection.extend({
model: AmenityModel,
getAmenitiesByHotelId: function(hotelId) {
return this.where({
hotelId: hotelId
});
}
});
ImageCollection = Backbone.Collection.extend({
model: ImageModel,
getImagesByHotelId: function(hotelId) {
return this.where({
hotelId: hotelId
});
}
});
var CombinationView = Backbone.View.extend({
template: _.template($("#hotel-list-template").html()),
initialize: function(){
this.hotels = new HotelCollection([],{
url: '<?php echo base_url(); ?>json_upload/hotels_details_<?php echo($this->session->userdata("id")); ?>.json'
});
this.amenities = new AmenityCollection([], {
url: '<?php echo base_url(); ?>json_upload/hotels_details_amenities_<?php echo($this->session->userdata("id")); ?>.json'
});
this.image = new ImageCollection([], {
url: '<?php echo base_url(); ?>json_upload/hotels_details_images_<?php echo($this->session->userdata("id")); ?>.json'
});
this.hotels.on("sync", this.hotelsLoaded, this);
this.amenities.on("sync", this.amenitiesLoaded, this);
this.image.on("sync", this.imagesLoaded, this);
this.hotels.fetch();
},
render: function(){
this.$el.html('Loading...');
return this;
},
hotelsLoaded: function(){
this.image.fetch();
this.amenities.fetch();
},
amenitiesLoaded: function(){
this.hotels.each(function(hotel) {
hotel.addAmenity(this.amenities.getAmenitiesByHotelId(hotel.id));
}, this);
},
imagesLoaded: function(){
this.hotels.each(function(hotel) {
hotel.addImage(this.image.getImagesByHotelId(hotel.id));
}, this);
},
displayCombinations: function(){
$(this.el).html(this.template({hotels: this.hotels.models}));
}
});
Can someone explain me why sometimes i see the image in the template and sometimes not?
This is a little piece of template with some console.log
<% _.each(hotels, function(hotel1, index_hotel) { %>
<%
console.log('hotel:');
console.log(hotel1);
console.log('amenities');
console.log(hotel1.amenities.models); %>
<% _.each(hotel1.amenities.models, function(am) {
//NOT ENTER HERE SOMETIMES!!!
if(am.attributes.image!=''){
var src = '<?php echo(base_url()); ?>/img/backend/ameneties/' + am.attributes.image;
}
else{
var src = '<?php echo(base_url()); ?>/img/backend/ameneties/NO_IMG.jpg';
}
%>
<% }
}
%>
The first log of hotel show the full hotel and inside it I see amenities.models with all, but in the log of ameneties is empoty like is t was loaded before.

Related

How to import json file into indexeddb?

I am doing an app that store some data in the IndexedDB, but I want to load first some data that is in my json file.
Here is my json file:
{
"ciudades":[
{
"ciudad":"Asuncion",
"latitud":-25.2985296,
"longitud":-57.6710677
},
{
"ciudad":"Caaguazu",
"latitud":-25.465034,
"longitud":-56.0183859
},
{
"ciudad":"Ciudad del Este",
"latitud":-25.4933441,
"longitud":-54.6710438
},
{
"ciudad":"San Pedro",
"latitud":-24.1586759,
"longitud":-56.636503
},
{
"ciudad":"Pedro Juan Caballero",
"latitud":-22.5450875,
"longitud":-55.7618963
}
]
}
you follow step
step 1 read mozilla site
step 2 create indexedDB
var ciudades = [
{
"ciudad":"Asuncion",
"latitud":-25.2985296,
"longitud":-57.6710677
},
{
"ciudad":"Caaguazu",
"latitud":-25.465034,
"longitud":-56.0183859
},
{
"ciudad":"Ciudad del Este",
"latitud":-25.4933441,
"longitud":-54.6710438
},
{
"ciudad":"San Pedro",
"latitud":-24.1586759,
"longitud":-56.636503
},
{
"ciudad":"Pedro Juan Caballero",
"latitud":-22.5450875,
"longitud":-55.7618963
}
];
var IDBSetting = {
name: "indexedDBName",
version: 1,
tables: [{
tableName: "ciudades",
keyPath: "seq",
autoIncrement: true,
index: ["ciudad", "latitud", "longitud],
unique: [false, false, false]
}]
};
! function() {
console.log("indexeDB init");
var req = indexedDB.open(IDBSetting.name, IDBSetting.version);
req.onsuccess = function(event) {
console.log("indexedDB open success");
};
req.onerror = function(event) {
console.log("indexed DB open fail");
};
//callback run init or versionUp
req.onupgradeneeded = function(event) {
console.log("init onupgradeneeded indexedDB ");
var db = event.target.result;
for (var i in IDBSetting.tables) {
var OS = db.createObjectStore(IDBSetting.tables[i].tableName, {
keyPath: IDBSetting.tables[i].keyPath,
autoIncrement: IDBSetting.tables[i].autoIncrement
});
for (var j in IDBSetting.tables[i].index) {
OS.createIndex(IDBSetting.tables[i].index[j], IDBSetting.tables[i].index[j], {
unique: IDBSetting.tables[i].unique[j]
});
}
}
}
}();
step 3 addData
var IDBFuncSet = {
//write
addData: function(table, data) {
var req = indexedDB.open(IDBSetting.name, IDBSetting.version);
req.onsuccess = function(event) {
try {
console.log("addData indexedDB open success");
var db = req.result;
var transaction = db.transaction([table], "readwrite");
var objectStore = transaction.objectStore(table);
var objectStoreRequest = objectStore.add(data);
} catch (e) {
console.log("addDataFunction table or data null error");
console.log(e);
}
objectStoreRequest.onsuccess = function(event) {
//console.log("Call data Insert success");
}
objectStoreRequest.onerror = function(event) {
console.log("addData error");
}
};
req.onerror = function(event) {
console.log("addData indexed DB open fail");
};
}
}
for(var i in ciudades){
IDBFuncSet.addData("ciudades",ciudades[i]);
}
step 4 getData
IDBFuncSet.getAllData = function(arr, table) {
try {
var req = indexedDB.open(IDBSetting.name, IDBSetting.version);
req.onsuccess = function(event) {
var db = req.result;
var transaction = db.transaction([table], "readonly");
var objectStore = transaction.objectStore(table);
var objectStoreRequest = objectStore.openCursor();
objectStoreRequest.onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
arr.push(cursor.value);
cursor.continue();
} else {
}
}
};
req.onerror = function(event) {
console.log("getAllData indexed DB open fail");
};
} catch (e) {
console.log(e);
}
}
var ciudadesArr = [];
IDBFuncSet.getAllData(ciudadesArr, "ciudades");
console.log(ciudadesArr);
I hope this helps
Here's how I've done mine, thanks to the android-indexeddb package.
angular.module('yourApp', ['indexedDB'])
.config(function($indexedDBProvider) {
$indexedDBProvider
.connection('dbName')
.upgradeDatabase(1, function(event, db, tx) {
var objStore = db.createObjectStore('storeOne', { keyPath: 'stop_id' });
objStore.createIndex('store_id', 'store_id', { unique: false });
})
// the next upgradeDatabase() function is necessary if you
// wish to create another datastore
.upgradeDatabase(2, function(event, db, tx) {
var secondObjectStore = db.createObjectStore('storeTwo', { keyPath: 'my_id' });
secondObjectStore.createIndex('another_id', 'another_id', { unique: false });
});
})
Then in my controller:
angular.module('yourApp')
.controller('homeCtrl', ['$scope', '$http', '$indexedDB', function($scope, $http, $indexedDB) {
$scope.objects = [];
var loadJSON = function(file_name) { ... //load the json file in here}
$indexedDB.openStore('storeOne', function(store) {
var loaded = loadJSON('file_name.json');
store.upsert(loaded).then(function(e) {
console.log('added successfully');
});
});
$indexedDB.openStore('times', function(store) {
var loaded = loadJSON('file_name.json');
store.upsert(loaded).then(function(e) {
console.log('added successfully');
});
});
}]);
Check out the project page to learn more of the tricks up this package's sleeves.
Although this angular-indexeddb page supports queries, for advanced queries like joins, you might wanna consider ydn-db
Getting some pretty nice workflow with both packages.
For the loadJSON() function, it could be something like this:
var loadJSON = function(file_name) {
var data;
$.ajax({
url: '../data/' + file_name,
dataType: 'json',
async: false,
success: function(res_data) {
data = res_data;
console.log('Loaded ' + file_name + ' nicely');
},
error: function(err) {
console.log('error happened');
}
});
return data;
}
There is File API, but that doesn't seem to be a solid standard yet.
What I do at the moment, is have the user open the file, copy it's contents to Clipboard, and paste it into a TextArea element on my web page.
In JavaScript I add a listener to the TextArea's change event and parse the text content into JSON, which is then written to indexedDB.

Backbone - json data not displayed in browser but rendering in console

I am able to see the json data in console, but not displayed in the html. I am not sure what change must be done to make it render in the browser.
Here is my code.
Model.js
var agent = Backbone.Model.extend({
});
var agentList = Backbone.Collection.extend({
model: agent,
url: 'data/agents.json',
});
View.js
var agentListView = Backbone.View.extend({
el: '.container',
initialize: function() {
this.template = _.template( tpl.get('agentList'));
},
render: function() {
var agents = new agentList();
agents.fetch({
success: function(agents) {
console.log(agents.toJSON());
}
});
this.$el.html(this.template({ AgentsList: agents.toJSON()}))
},
});
HTML
<% _.each(AgentsList, function(item) { %>
<tr>
<td>data</td>
<td><%= item.name%></td>
<td><%= item.gender%></td>
<td><%= item.birthYear%></td>
<td><%= item.skills%></td>
</tr>
<% }); %>
The problem is that you don't render the view in the callback, and therefore you won't have anything to show.
Besides, getting the list of agents inside the render function is definitely not something to do if you want to respect MVC principles. You should have something like:
var agentCol = new AgentList();
var agentView = new AgentListView({collection: agentCol});
agentCol.fetch({
success: function() {
agentView.render();
}
});
and your AgentListView should look like
var AgentListView = Backbone.View.extend({
el: '.container',
initialize: function() {
this.template = _.template(tpl.get('agentList'));
},
render: function() {
this.$el.html(this.template({ agents: this.collection.toJSON()}));
},
});
(I took the liberty to rename some variables to match naming conventions)
Its maybe because the time when the $el update code runs the agents collection is not loaded (fetched) yet.
May be you can update your render method with the code below, so that the $el shall be updated only when the collection fetch is returned from the server.
render: function() {
var $this = this;
var agents = new agentList();
agents.fetch({
success: function(agents) {
console.log(agents.toJSON());
$this.$el.html($this.template({ AgentsList: agents.toJSON() }));
}
});
}
Or an an alternative you can listen to the collection event (reset maybe) which fires whenever the data is fetched from the remote data source - json file in this case.
In that case the view code could be,
var agentListView = Backbone.View.extend({
el: '.container',
initialize: function() {
this.template = _.template( tpl.get('agentList'));
this.collection = new agentList();
this.listenTo(this.collection, "reset", this.addAgentsToDom);
},
render: function() {
this.collection.fetch({
success: function(agents) {
console.log(agents.toJSON());
}
});
},
addAgentsToDom: function(collection, options) { // please name the method whatever you want :)
this.$el.html(this.template({ AgentsList: this.collection.toJSON() }));
}
});

Backbone insert data inside Model from another

I have a simple app in backbone where the logic isn't clear for me, It's my second app and I don't know if is good the logic and how I have construct it.
The goal is when I load a page I want to retrieve all folders and files of a specific directory and print it.
I have create an app general where I include another app called Folder.
When I load the page I create the general app, search inside a folder and retireve folders and files into a json with an ajax function.
I have succesfull do that but my problem is how now populate my FolderView, FolderModel and Folder Collection?
Is necessary to do that I think but I don't know how to pass this json to FolderCollection/FOlderModel.
This is my appView
define(['jquery' , 'backbone', 'views/folder', 'models/folder', 'collections/folder', 'models/app'],
function($, Backbone, FolderView, FolderModel, FolderCollection, AppModel){
var AppView = Backbone.View.extend({
model: AppModel,
el:$('#folder'),
initialize: function(){
console.log('initialize AppView');
this.retrievFolderFile('uploads');
//prendo le cartelle e le metto nel json
this.folders = new FolderCollection();
this.render();
//this.todos.bind('sync', this.render, this);
//this.todos.fetch();
},
render: function(){
var element = this.$el;
element.html('');
this.folders.each(function(model){
var folderView = new FolderView({model:model});
element.append(folderView.el);
});
},
retrievFolderFile: function(dir){
var here = this;
console.log('retrieveFolderFile');
$.ajax({
type: "POST",
dataType: "json",
data: {"dir": dir},
url: 'function/retrieve_folder.php',
success: function(data) {
console.log(data);
// ------------------ HERE I HAVE RESULT HOW TO PASS TO FOLDER VIEW/ COLLECTION?------
}
});
}
})
return AppView;
});
This is my folderModel
define(['backbone'],function(Backbone){
var FolderModel = Backbone.Model.extend({
defaults:{
name:'Folder',
path:''
},
initialize:function(){
console.log('Initialized Folder model');
}
});
return FolderModel;
});
This is my FolderCollection
define(['backbone', 'models/folder'], function(Backbone, FolderModel){
var folderCollection = Backbone.Collection.extend({
model: FolderModel,
});
return folderCollection;
});
This is my FolderView
define(['jquery', 'underscore', 'backbone', 'text!templates/folder.html'], function($, _, Backbone, FolderTemplate){
var FolderView = Backbone.View.extend({
el:$('#folder'),
template: _.template(FolderTemplate),
initialize: function(){
console.log('FolderView initialized');
this.render();
},
render: function(){
console.log('FolderView render');
//$(this.el).html(this.template({model: this.options.model}));
}
});
return FolderView;
});
To retrieve folder and files I use this file PHP that return me a valid json to backbone
<?php
$dir = $_POST['dir'];
$data = fillArrayWithFileNodes( new DirectoryIterator( '../'.$dir ) );
function fillArrayWithFileNodes( DirectoryIterator $dir )
{
$data = array();
foreach ( $dir as $node )
{
if ( $node->isDir() && !$node->isDot() )
{
//$data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
$arr_to_insert = array();
$arr_to_insert['name'] = $node->getFilename();
$arr_to_insert['type'] = 'folder';
array_push($data, $arr_to_insert);
}
else if ( $node->isFile() )
{
//$data[] = $node->getFilename();
$arr_to_insert = array();
$arr_to_insert['name'] = $node->getFilename();
$arr_to_insert['type'] = 'file';
array_push($data, $arr_to_insert);
}
}
return $data;
}
echo json_encode($data);
?>
How to pass from appview the json that return me?
Is correct to do the folderand filde search inside appview or I have to do it inside folderModel?
Because after when I click on a folder I want to retrieve its file and folders again.
Help me to understand the logic and how to pass it.
I thought to call a function inside FolderCollection like parseFolderFile and insert it into a model but how?
Thanks
AJAX is asynchronous.. So you are making an ajax call and then calling the render method which is iterating over the collection and renders them.
But your data is not ready until and after the sucess callback, where I guess your collection will be populated. So you are supposed to populate the collection inside the success call back and then call render.
So something in these lines
initialize: function () {
console.log('initialize AppView');
this.folders = new FolderCollection();
this.retrievFolderFile('uploads');
},
render: function () {
var element = this.$el;
element.html('');
this.folders.each(function (model) {
var folderView = new FolderView({
model: model
});
element.append(folderView.el);
});
},
retrievFolderFile: function (dir) {
var here = this;
console.log('retrieveFolderFile');
$.ajax({
type: "POST",
dataType: "json",
data: {
"dir": dir
},
url: 'function/retrieve_folder.php',
success: function (data) {
console.log(data);
here.folders.set(data);
here.render();
}
});
}
Also why do you want to handle an ajax request , where there is already a native one provided by backbone.
You can declare the url in the collection do this.folders.fetch() , and then listen to the sync or the resent event which will be lot more cleaner in my view.
Using native Fetch
define(['jquery', 'backbone', 'views/folder', 'models/folder',
'collections/folder', 'models/app'],
function ($, Backbone, FolderView, FolderModel,
FolderCollection, AppModel) {
var AppView = Backbone.View.extend({
model: AppModel,
el: $('#folder'),
initialize: function () {
this.folders = new FolderCollection();
// This will automatically call the render once the
// collection is reset
this.listenTo(this.folders, 'reset', this.render);
this.folders.data = 'uploads';
this.folders.fetch();
},
render: function () {
var element = this.$el;
element.html('');
this.folders.each(function (model) {
var folderView = new FolderView({
model: model
});
element.append(folderView.el);
});
}
})
return AppView;
});
define(['backbone', 'models/folder'], function(Backbone, FolderModel){
var folderCollection = Backbone.Collection.extend({
model: FolderModel,
url : 'function/retrieve_folder.php' + this.data;
});
return folderCollection;
});

backbone fetch specific object from json file, not rendering

Okay, im going slightly insane trying to display data from a json file in 2 seperate views/collections.
I will paste my entire code here and try to explain where i am now, and what i need done.
Its probably a very small thing i just need to do in order for it to work, but i cant see it..
Here is a screen shot of how my page looks like now, as you can see the data is being loaded, i just cant get it into the views properly..
In my Collection class i call parse:
parse:function(response, options) {
return options.parseField ? response[options.parseField] : response;
},
i call sync: (not sure its needed at all)
sync: function(method, model, options) {
options.contentType = "application/json";
options.cache = false;
options.dataType = "json";
return Backbone.sync(method, model, options);
},
Then near the bottom, i create 2 new collections and use fetch to get the specific json data i need for each collection like so:
var links = new App.Collections.Links();
links.fetch({
parseField: 'links_1',
success: function () {
console.log(links.toJSON());
return links.toJSON();
}
});
var links2 = new App.Collections.Links();
links2.fetch({
parseField: 'links_2',
success: function () {
console.log(links2.toJSON());
return links2.toJSON();
}
});
I do console.log and can see that my json data is getting loaded just fine, but its not getting rendered ?
What am i doing wrong here..
For sake of debugging and understanding i have included my entire js file below.
(function() {
// Helper functions
// Defining namespacing rules
window.App = {
Models: {},
Collections: {},
Views: {}
};
// Setting global template function, for simpel declaration later on by setting template('name'); for the built in template function.
window.template = function(id) {
return _.template( $('.' + id).html() );
};
// Capitalize first letter in a link by adding .capitalize(); to the string.
String.prototype.capitalize = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
};
// Extending Backbone
//Modellen
App.Models.Link = Backbone.Model.extend({
defaults: {
navn : 'i haz a name!',
link : 'http://www.lolcats.com/',
counter : 0
}
});
//Collection
App.Collections.Links = Backbone.Collection.extend({
model: App.Models.Link,
url: 'data1.json',
parse:function(response, options) {
return options.parseField ? response[options.parseField] : response;
},
sync: function(method, model, options) {
options.contentType = "application/json";
options.cache = false;
options.dataType = "json";
return Backbone.sync(method, model, options);
},
// Sort the models 'highest first'
comparator: function(link) {
return -link.get('counter');
}
});
//Singel view
App.Views.LinkView = Backbone.View.extend({
tagnavn: 'li',
template: template('Links'),
initialize: function() {
this.model.on('change', this.render, this);
this.model.on('destroy', this.remove, this);
},
events: {
'click .edit' : 'retLink',
'click .delete' : 'destroy',
'click .LinkUrl' : 'addCounter'
},
retLink: function() {
var newLinkNavn = prompt('What should the new name be?', this.model.get('navn'));
if ( !newLinkNavn ) return;
newLinkNavn = newLinkNavn.capitalize();
this.model.set('navn', newLinkNavn);
var newLinkUrl = prompt('What should the new url be?', this.model.get('link'));
if ( !newLinkUrl ) return;
this.model.set('link', newLinkUrl);
},
destroy: function() {
this.model.destroy();
},
// Increment the counter then user clicks it
addCounter: function(e) {
e.preventDefault();
var newCounter = this.model.get('counter');
this.model.set('counter', newCounter + 1);
},
remove: function() {
this.$el.remove();
},
render: function() {
this.$el.html(this.template(this.model.toJSON()) );
return this;
}
});
//Collection View
App.Views.LinksView = Backbone.View.extend({
tagName: 'ul',
className: 'liste',
initialize: function() {
_.bindAll(this);
this.collection.on('add', this.addOne, this);
this.collection.on('reset', this.render);
// Render view when a user has changed a model
this.collection.bind('change', this.render, this);
$('.navnClass').focus();
this.load();
this.render();
},
load: function() {
this.collection.fetch({
add: true,
success: this.loadCompleteHandler,
error: this.errorHandler
});
},
loadCompleteHandler : function(){
this.render();
},
errorHandler : function(){
throw "Error loading JSON file";
},
render: function() {
// Empty the UL before populating it with the new models and sorting it.
this.$el.empty();
this.collection.sort();
this.collection.each(this.addOne, this);
return this;
},
addOne: function(link) {
var linkView = new App.Views.LinkView({ model: link });
this.$el.append(linkView.render().el);
}
});
// Create link view
App.Views.AddLink = Backbone.View.extend({
el: '#addLink',
events: {
'submit' : 'submit'
},
submit: function(e) {
e.preventDefault();
var linkNavn = $(e.currentTarget).find('.navnClass').val(),
linkNum = $(e.currentTarget).find('.linkClass').val();
// Tildel link navn en værdi, hvis det er tomt
if ( ! $.trim(linkNavn)) {
linkNavn = 'I haz a name!';
}
// Tildel link url en værdi, hvis det er tomt
if( ! $.trim(linkNum)) {
linkNum = 'http://www.lolcats.com/';
}
// Tilføj http:// foran værdi, hvis den ikke indeholder det i forvejen.
if( linkNum.indexOf( "http://" ) == -1 ) {
addedValue = 'http://',
linkNum = addedValue + linkNum;
}
// nulstil og sæt fokus på link navn feltet.
$(e.currentTarget).find('.navnClass').val('').focus();
$(e.currentTarget).find('.linkClass').val('');
this.collection.add({ navn:linkNavn, link: linkNum });
}
});
// new links collection
// populate collection from external JSON file
// change navn to match the link heading
var links = new App.Collections.Links();
links.fetch({
parseField: 'links_1',
success: function () {
console.log(links.toJSON());
return links.toJSON();
}
});
var links2 = new App.Collections.Links();
links2.fetch({
parseField: 'links_2',
success: function () {
console.log(links2.toJSON());
return links2.toJSON();
}
});
// new collection view (add)
var addLinkView = new App.Views.AddLink({ collection: links });
// new collection view
var linksView = new App.Views.LinksView({ collection: links });
$('.links').html(linksView.el);
// new collection view
var linksView2 = new App.Views.LinksView({ collection: links2 });
$('.links2').html(linksView2.el);
})();
Could you try this:
var links2 = new App.Collections.Links();
links2.on("reset", function(collection){
console.log("reset event", collection);
}
links2.fetch({
parseField: 'links_2',
wait:true, #wait for the server to respond
success: function (collection, response) {
console.log(collection, response);
}
});
a return in the success call doesn't do anything (it would return to the $.ajax object). I've added a wait because it would call the successcall instantly if it passes the clientside validation (you have none, so it would always call success first).
You say it doesn't render anything. But to render something you need a View. I don't see a view in your code.
Here's a quick example of the view:
var Link = new Backbone.View.extends({
el: $('body'),
initialize: function(){
this.listenTo(this.collection, 'reset', this.render, this)
},
render: function(){
this.$el.empty();
this.collection.each(function(item){
this.$el.append(item.get('id') + '<br />');
});
}
})
var view = new Link({collection: links2});

Backbone.js + REST

Im very new to Backbone.js and have been following a couple tutorials to come up with the script below. What I am trying to achieve is retrieving JSON data from a rest api when my routes are used. If you look at the people function for the friends route you can see where im going with this. Where am i going wrong?
<!DOCTYPE html>
<html>
<head>
<title>I have a back bone</title>
</head>
<body>
<button id="add-friend">Add Friend</button>
<ul id="friends-list">
</ul>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
<script>
Friend = Backbone.Model.extend({
name: null,
age: null,
});
FriendDetailModel = Backbone.Model.extend();
FriendDetailCollection = Backbone.Collection.extend({
url: 'slim/index.php/friends/',
model: FriendDetailModel
});
Friends = Backbone.Collection.extend({
initialize: function(models, options) {
this.bind("add",options.view.addFriendLi);
}
});
AppView = Backbone.View.extend({
el: $("body"),
initialize: function() {
this.friends= new Friends(null, {view:this});
},
events: {
"click #add-friend": "showPrompt",
},
showPrompt: function () {
var friend_name = prompt("Who is your friend?");
var friend_age = prompt("What is your friends age?");
var friend_model = new Friend({name: friend_name, age: friend_age});
this.friends.add(friend_model);
},
addFriendLi: function(model) {
$("#friends-list").append("<li>" + model.get('name') + " " + model.get('age') + "</li>");
}
});
var appview = new AppView;
AppRouter = Backbone.Router.extend({
routes: {
"friends":"people",
"person/:name":"personDetail"
},
people: function() {
console.log('all the people');
var people = new FriendDetailCollection;
people.fetch({
success: function(data) {
console.log(data);
}
},
personDetail: function(name) {
console.log('one person named ' + name);
}
});
var approuter = new AppRouter;
Backbone.history.start();
</script>
</body>
</html>
after running people.fetch Console.log shows
d
_byCid: Object
_byId: Object
length: 4
models: Array[4]
__proto__: x
If i do console.log(data.toJSON()); it returns
[]
I ended up resolving the problem by doing the following:
I created a new collection outside of the router:
var people = new FriendDetailCollection;
When I created the view I specified the collection I previously created.
friendview = new FriendView({collection: people});
I had a typo in my FriendView. Previously I had _.bind(this, 'render'). It need to be
_.bindAll(this,'render');
Also, i put my console.log in the render() function within my FriendView.
FriendView = Backbone.View.extend({
el: $("body"),
initialize: function() {
_.bindAll(this,'render');
this.collection.bind('reset', this.render);
},
render: function() {
console.log(this.collection.toJSON());
}
});