I'm having an issue wrapping my head around relational models in Backbone. I've just started using it and I'm tasked with a fairly large application.
The main issue I'm having is that I have a model that should contain a collection.
This is what I have to work with:
modelA
id: _id
url: api/model/:modelA_id
nested:
url: api/:modelA_id/nest
I think I'm making it a bigger deal than I need to, but I just can't seem to wrap my head around how to set this up.
Any help will be most appreciated.
The biggest thing to wrap your head around with Backbone is how to properly use events to deal with basically everything in the app. The other big thing to understand is that there are probably 5 different ways to attack a problem, where none of them are better/worse than the other.
Given that loose structure you've provided, I would do something like:
var YourApp = {
Models : {}
Collections : {}
Views : {}
};
YourApp.Models.First = Backbone.Model.extend({
initialize : function(){
var nestedCollection;
this.url = 'api/model/' + this.id;
nestedCollection = new Backbone.Collection({
url : this.url + '/nest'
});
this.set('nested', nestedCollection);
}
});
new YourApp.Models.First({
id : 23
});
Related
I over complicated things at first and could not figure out how to create a list within a list using backbone.js. I finally got it, by simply creating a list item view for all of the players in my app. Then created a view for all of the teams inside my app.
I "glued" or "appended" them together by creating an app view that put them together, there is an each statement for both, before the two views were appended to the app view root, I appended the player list item view into the team view. Let me show you.
Here is my render method inside the app view: I am just not sure if this is a bad idea or not, I am thinking there are much better ways, but this is the only method I have had success with. It really makes sense to me, I can run events on each view without a problem
render: function() {
var self = this;
this.teams.each(function(team) {
var teamView = new TeamView({ model: team });
var teamHtml = teamView.render().el;
var teamPlayers = this.players.where({team_id: team.get('id')})
_.each(teamPlayers, function(player) {
var playerView = new PlayerView({ model: player });
var playerHtml = playerView.render().el;
$(teamHtml).append(playerHtml);
}, this);
this.$el.append(teamHtml);
}, this);
return this;
},
I asked about this and was told it would be better to create sub-views, well I am pretty sure this is a sub-view structure? Are there any holes to this method, if so I would like an explanation why this method is bad and how I can improve it. Last but not least I do care about clean maintainable code but what matters most is that I have teams wrap its respected players with an HTML result like below.
<div>
<ul class="lakers">
<li>Kobe</li>
<li>Pau</li>
</ul>
<ul class="spurs">
<li>Tony</li>
<li>Tim</li>
</ul>
</div>
Again id like some constructive criticism, mainly PROS & CONS with connecting the two views like that. Just needed to ask before I move on I want to make sure I am not getting into bad habits or creating problems in my code when I start expanding it, I am sure you understand that.
I asked about this and was told it would be better to create sub-views, well I am pretty sure this is a sub-view structure?
Yes you knew it, and TeamView is sub-view. However it's a "zombie view". Does it do anything itself? A view should be responsible of rendering itself, including appending its direct sub-views, but without knowing how to render its sub-views, i.e., you should pass the players collection to the TeamView and move the following logic into TeamView:
var teamPlayers = this.players.where({team_id: team.get('id')})
_.each(teamPlayers, function(player) {
var playerView = new PlayerView({ model: player });
var playerHtml = playerView.render().el;
$(teamHtml).append(playerHtml);
}, this);
I'm relatively new to Backbone and I'm trying to use a PageableCollection in my application.
https://github.com/wyuenho/backbone-pageable
Could someone please point me, what am I doing wrong? I'm using backbone 1.0.0
I have a collection and a model defined like this:
var VoteList = Backbone.PageableCollection.extend({
model: Vote,
url: config.service + 'votes'
});
var Vote = Backbone.Model.extend({
url: function () {
return config.service + 'vote/' + this.id;
}
});
Later in the application:
this.collections.voteList = new VoteList([], {mode: "client", state: {pageSize: 12}});
....
this.collections.voteList.remove(options.model);
PageableCollection.remove() method fires a DELETE event which uses the URL of VoteList collection(?) to access a web service which in turn produces me an error 405 "Method not allowed" as a DELETE method is supposed to have an {id}
#DELETE
#Path("/vote/{id}")
#Consumes({MediaType.APPLICATION_JSON})
public void deleteVoting(#PathParam("id") Integer id) {
log.info("deleting " + id.toString());
}
When I remove pagination just by instantiating normal Backbone.Collection
var VoteList = Backbone.Collection.extend({ ... });
everything works as expected, Backbone uses a model url + id when deleting. So my question is how to make the PageableCollection to behave just in the same way?
This morning got a mail from the plugin author, it appears to be a known bug in Backbone 1.0.0. I guess it will gone away with version 1.0.1
Please see this thread: https://github.com/wyuenho/backbone-pageable/issues/70
To solve problem now I used a latest 'master' branch of Backbone which has this issue fixed:
https://raw.github.com/jashkenas/backbone/master/backbone.js
Alternatively, if you can't for some reason use a development branch, a temporary solution like this will also work:
var Vote = Backbone.Model.extend({
initialize: function () {
this.url = function () {
return config.service + 'vote/' + this.get('id')
}
}
});
Upgrading to backbone 1.1.0 seems to resolve this problem.
I ran into the same exact issue with backbone 1.0.0 collections extended by backbone-pageable.
Heads up! Be sure to keep an eye on the 1.1 upgrade notes since backbone 1.1 isn't fully compatible to 1.0 code, such asoptionspassed to views are no longer automatically available as this.options.
In my bb router I get some JSON data
$.ajax({
url: "js/projects.json",
success: function(projects) {
database.projects = projects;
var variables = {};
var niz = new Array();
var param = "Client"
$.each(projects, function()
{
if (!variables[this[param]])
variables[this[param]] = [];
variables[this[param]].push(this);
});
for(var d in variables) {
niz.push(d);
var number_of_clients = niz.length;
}
console.log(number_of_clients);
Backbone.history.start();
}
});
Now I wanna access this "projects" from one of my Views and to some stuff with that data , I know I can do the same thing again like here , but its duplicating code , is there any way to get this data in View ? I tried a few things but with no success , I allways get the undefined
You can attach your data to the window (window.projects = projects), then you can access it from everywhere. But I recomend you to use the ajax tools from Backbone, it's much easier and less messy.
Honestly, your question seems very suspicious design-wise. :)
Ajax calls should be made in models using the fetch function, not in a router, and not using jquery directly.
So I would advise you to redesign your app unless you have a strong reason not to do so.
So I have inherited a bit of backbone.js code and need to make a change to it today. The guy who wrote the original code is on vacation. I am just barely studying up on backbone.js and am pretty much a backbone newbie.
The code below works and does what it was designed for. There is only one issue: The contents of the template file (see below) get rendered into a specific HTML page.
My problem is that I don't fully understand the flow of the code to make an educated guess as far as how and where to insert a reference to an actual container on that HTML page, and get the content to display inside that container.
The class name of the container where I need the output from this function to go is .mngmnt-main-sctn. Is this possible to do?
.
window.ManagementInstancesBackupView = ManagementView.extend({
events: _.extend({
}, ManagementView.prototype.events
),
initialize: function() {
this.model = this.options.model
this.collection = this.options.collection
this.template = _.template($('#instances-management-backup-template').html())
},
render: function() {
var instances = this.collection
// Append container and title
var $el = this.$el.html(this.template({}))
instances.each(function(instance) {
// THIS IS THE CONTAINER THAT SHOULD GET STUFF APPENDED TO:
// $(".mngmnt-main-sctn")
$el.append(this.renderParent(instance));
instance.get('nic').each(function(nic) {
$el.append(this.renderChild(nic));
}, this)
}, this)
return this
},
renderParent: function(instance) {
return new ManagementInstancesBackupParentView({model: instance}).render().$el
},
renderChild: function(nic) {
return new ManagementInstancesBackupChildView({model: nic}).render().$el
}
});
I believe what you are asking is possible like this.
window.ManagementInstancesBackupView = ManagementView.extend({
el: ".mngmnt-main-sctn"
[...code excluded...]
});
We are overriding the el property meaning that when this line is called
var $el = this.$el.html(this.template({}))
this.$el will refer to the element you have specified.
Jacob, thanks again for looking into this.
I found a solution and now I'm definitely going to hit additional backbonejs tutorials. Within the code, I was able to add the selector like so:
// Append container and title
var $el = this.$el.html(this.template({})).find('.mngmnt-main-sctn')
.
I'm always perplexed by stuff like this. You can't find any answers to solve the problem, then you try a 1,000 different things . . . and then the solution seems so simple and I always feel a bit foolish after such an experience.
I'm relativly new to Backbone.js
I have a JSON like the picture shows !
I saw some Answers in relation with Backbone-relational, but still dont get the point!
How can i convert this JSON to Backbone.js Collections/Models??
I update with a code but it dont work like expected! i can't see an model when i do :
My Structure is :
[0] : is a collection of models
[clefs] + ... + [Rest] : are collection of models
(clefs) => [0] + ... + [9] : are Models(title contains a string, path too)
Thanks a lot!!
EDIT(10.01.12) :
My Solution :
window.initModel = Backbone.Model.extend({
defaults: {
"title": "",
"path": ""
}
});
window.CustomCollection = Backbone.Collection.extend({
model: initModel
});
window.Init = Backbone.Model.extend({
url : function(){
return "/api/data.json"
},
parse: function(response) {
clefs = new CustomCollection();
clefs.add(response.clefs);
this.set({clefs: clefs});
.....
rests = new CustomCollection();
rests.add(response.rests);
this.set({rests: rests});
}
});
this helped me out too!
I'm at work, so I cannot give you a fully coded answer, but the gist is, you can do the following in your top level models to achieve a nested model hierarchy:
var AmericasNextTopModel = Backbone.Models.extend({
initialize: function(){
this.set({
clefs: new ClefCollection(this.get('clefs')),
accidentals: new AccidentalCollection(this.get('accidentals')),
notes: new NoteCollection(this.get('notes')),
rests: new RestCollection(this.get('rests'))
});
}
});
I do not use backbone-relational so I cannot give you an answer regarding that.
Are you making an online sheet music viewer/editor? :D Cool I'd love to see it when you're done.
The reset method (see 'reset') allows you to pass a JSON array to a collection.
This is the equivalent of a PUT method, replacing the specified collection with the JSON hash.
You can also use the add method to add to an existing collection, or pass the JSON hash into the constructor as you create a new collection.
You'll have to do some basic cleaning up of your array to get it in an appropriate format, and then convert it to JSON
I'm using PHP to grab a feed as JSON since it's on a different domain. I save those results to a JS variable, and then I just had success using this to get it into my Backbone collection...
var feedCollection = new Backbone.Collection();
feedCollection.set(myFeedJSON.nestedObject.nestedArrayIWant);