i've a userlist made by a fetch from parse.com and rendered by view.Once people click on item list i've insert in url the objectid. In router i've made a function "home" that make fetch from collection and call view to render.The function "userdetails" catch objectid previous insert by view in url and use it to make a get from collection. The problem is:how can i pass the collection to this function userdetails?I don't want make another fetch.
home: function() {
var self=this;
console.log("inrouterhome");
var utenti = new Usercollection();
utenti.fetch({
success: function(object) {
var page=new Homelistuser({model:object});
self.changePage(page);
},
error: function(amici, error) {
// The collection could not be retrieved.
}
});
},
userDetails: function (objectId) {
HERE I WANNA USE OBJECTID TO MAKE A GET FROM COLLECTION FETCHED IN HOME
},
It looks like it is probably a scoping issue. Try this
var Models = {};
var AppRouter = Backbone.Router.extend({
home: function() {
var self=this;
console.log("inrouterhome");
Models.utenti = new Usercollection();
Models.utenti.fetch({
success: function(object) {
var page=new Homelistuser({model:object});
self.changePage(page);
},
error: function(amici, error) {
// The collection could not be retrieved.
}
});
},
userDetails: function (objectId) {
//Models.utenti should exist as long as home came first,
// may want to write a condition that check to see if it exists and if not do fetch.
}
});
As #abritez mentioned this is probably a scoping problem i.e. the userDetails method doesn't have access to the instantiated collection. #abritez's solution resolves this but if the user refreshes the page or accesses the route directly the collection will not be loaded.
If the collection is used between both routes consider fetching it at run time and using a listener for when it's ready:
var Models = {};
Models.utenti = new Usercollection();
Models.utenti.fetch();
var AppRouter = Backbone.Router.extend({
home: function() {
var utentiLoaded = function(object) {
var page = new Homelistuser({model:object});
this.changePage(page);
}
this.listenTo(Models.utenti, 'reset', utentiLoaded);
this.listenTo(Models.utenti, 'error', function(amici, error) {
// The collection could not be retrieved.
});
if (Models.utenti.any()) {
utentiLoaded(Models.utenti);
}
},
userDetails: function(objectId) {
var utentiLoaded = function(object) {
}
this.listenTo(Models.utenti, 'reset', utentiLoaded);
this.listenTo(Models.utenti, 'error', function(amici, error) {
// The collection could not be retrieved.
});
if (Models.utenti.any()) {
utentiLoaded(Models.utenti);
}
}
});
Related
I have a collection below
var Collection = Backbone.Collection.extend({
model: Model,
url: 'messages',
defaults :{
subject: 'this is subject',
message: 'This is message'
}
});
Now what I want is when the ajax request to message is failed the I want to my app to use defaults data but my current app does not use that.
Below is the way I am using it.
var collection = new Collection();
collection.fetch().then(function () {
new SomeView({ collection: collection });
}, function (status, error) {
new SomeView({ collection: collection });
});
What I am doing in above code is if fetch is successful or failed still I am calling the same view and passing the same collection. Now when it is failed then collection should have defaults contents.
But it does not have them unfortunately.
The main purpose of doing this way is I want my application to work even if there is not server available should be able to work with static data present in default attribute in collection.
Is it possible if yes then how can I make it work?
The defaults are set in the model instead of the collection. What you can do in case the fetch fail is to add a new model to the collection with the default values:
var Model = Backbone.Model.extend({
defaults :{
subject: 'this is subject',
message: 'This is message'
}
});
var Collection = Backbone.Collection.extend({
model: Model,
url: 'FakeUrl/messages'
});
var collection = new Collection();
collection.fetch().then(function () {
new SomeView({ collection: collection });
}, function (status, error) {
//adds new model with default values, same as collection.add(new Model());
collection.add({});
console.log(collection.toJSON());
new SomeView({ collection: collection });
});
Another option is to initially create the collection containing a single model with the default values. Then pass {reset:true} when fetching the data from the server. If fetch succeeds the default model will be removed, but if it fails the collection will still contain it:
var collection2 = new Collection(new Model());
collection2.fetch({reset: true}).then(function () {
new SomeView({ collection: collection });
}, function (status, error) {
console.log(collection2.toJSON());
new SomeView({ collection: collection });
});
You can try both options in this fiddle
I have an application that reads/create/update model and save it to the server. But presently I am able to read and save my models from and to the database. But I am unable to delete / update the model from and to the server. currently the views gets deleted of the model but not the model it self
here is the JSFiddle path http://jsfiddle.net/u17xwzLh/1/
$(function() {
Model
var modelContact = Backbone.Model.extend({
defaults: function() {
return {
Id: 0,
Name: "",
Address: ""
};
},
//if i add this idAttribute = "Id" it deletes the value from the server
//but i am unable to create a new model/new entry to the database
clear: function () {
// Deletes the model but the changes are not posted back to the server
this.destroy();
}
});
Collection
// runs fine
var contactCollection = Backbone.Collection.extend({
model: modelContact,
url: 'api/Contact'
});
var contacts = new contactCollection;
ModelView
var contactView = Backbone.View.extend({
tagName: "tr",
events: { // runs fine
"click a.destroy": "clear"
},
template: _.template($("#newContacttemplate").html()), // runs fine
initialize: function() {
this.model.on("change", this.render, this);
this.model.on('destroy', this.remove, this);
},
render: function() { // runs fine
this.$el.html(this.template(this.model.toJSON()));
return this;
},
clear: function () {
this.model.clear();
}
});
MainView
var main = Backbone.View.extend({
el: $("#contactApp"),
events: { // runs fine
"click #btnsave": "CreateNewContact"
},
initialize: function() { // runs fine
this.Nameinput = this.$("#contactname");
this.Addressinput = this.$("#contactaddress");
contacts.on("add", this.AddContact, this);
contacts.on("reset", this.AddContacts, this);
contacts.fetch(); // Note : populates all the database values
},
AddContact: function(contact) { // runs fine
var view = new contactView({ model: contact });
this.$("#tblcontact tbody").append(view.render().el);
},
AddContacts: function() { // runs fine
contacts.each(this.AddContact);
},
CreateNewContact: function(e) { // runs fine
contacts.create({ Name: this.Nameinput.val(), Address: this.Addressinput.val() });
}
});
var m = new main;
});
Right now you have a URL defined on your Backbone.Collection but not on your Backbone.Model, which means you have to do all AJAX work through the Collection. It doesn't have to be that way though: you can add a second URL on yours server-side for Model AJAX operations, or the two could even share a URL (if you set it up appropriately).
The important part, if you want to be able to call this.destroy(); and have it reflected on your server, is that you need:
a URL on your server that can handle requests with the DELETE method (vs. the usual GET or POST methods)
a url property on your Backbone.Model that is set to that server-side URL
Once you have that your call to this.destroy(); will create a DELETE AJAX request, your server will receive that request and know that it should delete the appropriate database record, and then that model will be deleted on both the client- and server-side.
is my first question here, so I please about some patience and forgive my english:)
When I type link in browser address bar, all is OK. But when I do this inside browser by clicking element, collection is empty. But the main problem is there is always the same response from server, but fetch "dont load" any items, so view render empty collection.
I use Backbone Boilerplate,
Browser.Views.Catalog - it is Backbone.View
Browser.Catalog - it is of Backbone.Collection
My router:
var Router = Backbone.Router.extend({
routes: {
'' : 'browse'
},
refreshCatalog: function(folder){
app.layout.setViews({
"#catalog" : new Browser.Views.Catalog({
collection: app.catalog
})
}).render();
},
browse: function(folder){
app.catalog = new Browser.Catalog();
app.folders.fetch({
error: function() { console.log(arguments); },
success: this.refreshFolders(folder),
data: $.param({folder: folder}),
cache:false
});
//app.catalog = new Browser.Catalog();
app.catalog.fetch({
error: function() { console.log(arguments); },
success: this.refreshCatalog(folder),
data: $.param({folder: folder}),
cache:false
});
},
I belive you should set the catalog in the initialize function
app.catalog = new Browser.Catalog();
should go in here ( add this function)
initialize: function (options) {
app.catalog = new Browser.Catalog();
}
the initialize function is called when the page is loaded so when browsing to #catelog it will have been set http://backbonejs.org/#Router-constructor
I want to map JSON having hierarchical structure onto Model. I can map the data at a top hierarchy onto Model. However, I can't map it onto Model which nested the element which I nested.
JSON
{
"attr1":"data1",
"chi1": {
"attr1":"chi1_data"
},
"list1":[
{"name":"name1"},
{"name":"name2"}
]
}
JavaScript
var Child2 = Backbone.Model.extend({
fun1:function() {
alert("this is Child2");
}
});
var List1 = Backbone.Collection.extend({
url: "list1",
model: Child2,
fun1:function() {
alert("this is List1");
}
});
var Child1 = Backbone.Model.extend({
});
var Root1 = Backbone.Model.extend({
url: "sample.json",
defaults : {
list1 : new List1,
chi1 : new Child1,
}
});
var View1 = Backbone.View.extend({
el: "#friends",
events: {
"click button": "sample"
},
initialize: function() {
this.root1 = new Root1();
},
sample: function() {
this.root1.fetch({
success: function(model) {
// this is success
alert(model.get("attr1"));
// this is error
alert(model.get("list1").fun1());
// this is error too.
model.get("list1").each(function(attr) {
alert(attr.fun1());
});
},
error: function(model, res) {
alert("error: " + res.status);
}
});
},
});
You might want to take a look at this plugin.
http://documentup.com/afeld/backbone-nested/
Might not be exactly what you want, but it could at least point you in the right direction.
The other thing you can do is override the parse method on your model...
parse: function(resp){
// And setup the model using the raw resp
// The resp data is your json from the server and will
// be used to setup the model. So overriding parse, you can
// setup the model exactly they way you want.
return resp;
}
thank you jcreamer.
backbone-nested plugin seems to be different from what I want to do.
I can realize the nest of the model. In using parse function.
// it is able to get "chi1_data"
new Child2(JSON.parse(JSON.stringify(resp["chi1"]))).get("attr1")
// it is able to get "name2"
new Child2(JSON.parse(JSON.stringify(new List1(JSON.parse(JSON.stringify(resp["list1"]))).get(2)))).get("name")
I found Backbone-relational plug in. I will try this
https://github.com/PaulUithol/Backbone-relational
I am calling my api which returns a task object via json (example return json below):
[{"pkTaskId":"96","fldName":"Change page to template","fldStatus":"Assigned","fldNotes":"http:\/\/williamsconcepts.com\/ci\/codeigniter\/libraries\/template\/reference.html\r\n\r\n111","fldDateDue":"0000-00-00 00:00:00","fldDateCompleted":"0000-00-00 00:00:00"},{"pkTaskId":"103","fldName":"fix list creation","fldStatus":"Assigned","fldNotes":"for some reason there is an SQL syntax error\r\n\r\nok","fldDateDue":"0000-00-00 00:00:00","fldDateCompleted":"0000-00-00 00:00:00"},{"pkTaskId":"104","fldName":"navicat db admin tool","fldStatus":"Assigned","fldNotes":"Try this out:\nhttp:\/\/www.navicat.com\/download\/download.html","fldDateDue":"0000-00-00 00:00:00","fldDateCompleted":"0000-00-00 00:00:00"},{"pkTaskId":"105","fldName":"Styling dropdowns","fldStatus":"Assigned","fldNotes":"Link:\nhttp:\/\/jqueryui.com\/demos\/autocomplete\/#combobox","fldDateDue":"0000-00-00 00:00:00","fldDateCompleted":"0000-00-00 00:00:00"},{"pkTaskId":"147","fldName":"api create task","fldStatus":"Assigned","fldNotes":"","fldDateDue":"0000-00-00 00:00:00","fldDateCompleted":"0000-00-00 00:00:00"}]
$(function(){
window.Task = Backbone.Model.extend({});
window.TaskList = Backbone.Collection.extend({
model: Task,
url: "http://localhost/tasker/index.php/api/tasks/username/lucasmp"
});
window.tasks = new TaskList();
window.AppView = Backbone.View.extend({
initialize: function() {
tasks.fetch({
success: function() {
console.log(tasks.toJSON());
}
});
}
});
window.App = new AppView;
});
$('#fetch').click(function(){
tasks.fetch({
success: function() {
alert("success");
console.log(tasks.toJSON());
},
error: alert("error")
});
});
I'm having an issue though with my fetch.click occurring twice; Once returns fetch error, then returns fetch success. What could be causing this to be fired twice?
Pls try this
error: function(){alert("error")}