backbone.js model extends another model - javascript

I'm building a dashboard application with Backbone.js
There is a grid of panes called modules. Each module has its own custom data that it needs to listen to.
In this sense, I have created a backbone model called Module that is basically the top-level information for each module like module_name & module_description
my first inclination is to find a way to make a new special module model per module... like a "counter" module, a "messages" module, etc.
how should I approach the separate & different data per module? any design pattern recommendations?

You can do something like this:
var Module = Backbone.Model.extend({
// default properties/methods of this module
});
var MessageModule = Module.extend({
// new properties/methods of this module
});

Related

Auto defining a custom JS Library in BackboneJS

I've created an JS library to handle all my API calls.
Is there a way to automatically include this in all my views as api without needing to define it at the top of each view?
I've tried adding it to the main js file, but that doesn't seem to carry into the views.
Each Backbone model should handle its API endpoint communications and each module should only require the models it depends on. Otherwise, it goes against the point of making your code more modular.
That being said, if you just want your API lib to be available everywhere, there are some ways to achieve that and the reason your tries failed is because every module was defined without the API as a dependency, so the order each module is created is not necessarily the one you think.
You need to ensure that your API module is defined after Backbone, but before everything else. One way I like is to create an overriding module.
Make a new module, (e.g. backbone.extension.js).
Override whatever you want with Backbone.
Use the map config option to point the dependency named backbone of each module to your new module.
Again, with the map option, make your new module points to the original backbone.
Why use the map option?
Because I like to have every paths defined correctly inside the require config. I don't want any library paths to be inside one of my custom module. If it changes, I only need to change it in one place.
How to configure require to override Backbone?
Make your module, say custom/plugins/backbone.extension.js.
Then, configure the paths and map them to the right file:
paths: {
"backbone": "lib/backbone/backbone",
"backbone.extension": "custom/plugins/backbone.extension"
},
map: {
"*": {
// every module should use our custom module.
"backbone": "backbone.extension",
},
// our custom module should use the original backbone
"backbone.extension": { "backbone": "backbone", },
},
How to override Backbone?
Make a module which depends on Backbone and your API library.
defined(['backbone', 'api'], function(Backbone, api){
var View = Backbone.View;
var BackboneExtView = View.extend({
api: api
});
Backbone.View = BackboneExtView;
// or, for this simple case
Backbone.View.prototype.api = api;
retrun Backbone;
});
One problem that could arise is if your API module needs Backbone. If it's the case, you could add an exception to the map config so your API requires the original Backbone and it avoids a circular dependency.

Confusion on Backbone Marionette and Require interaction for getting dependencies

I am mildly familiar with require.js and Backbone.js having used them together for about a year now and relatively new to Backbone.Marionette although I am very interested in what it can bring to the table.
In looking for examples of project structure (I can get a little obsessed with this stuff) I have found https://github.com/BoilerplateMVC/Marionette-Require-Boilerplate and other similar examples.
Something that has been bothering me: in their app.js file, they return a reference to an instance of a Marionette application, ie:
var app = new Backbone.Marionette.Application();
app.addInitializer(...);
...
return app;
And in many components, they reference the app.js via require.js and use as follows:
define([..., 'app'], function (... , App) {
App.someProperty(...);
});
Now here's what I'm not understanding: I have been under the assumption that the code in their app.js is really more like a Factory than a Class since it returns an instance of an application rather than, say, a modified prototype or extension thereof.
Therefore, when they reference app.js, aren't they actually creating a whole new instance rather than accessing some sort of shared instance? There is nothing to suggest that app.js is returning a singleton in their code.
And yet, it works, and obviously I am the one who is confused.
So, why does this work?
This works because objects are passed by reference in javascript and the fact that require.js only loads every dependency once. Then, app.js returns an initialized instance, and every other module that requires 'app' gets reference to the same object.
It's not a factory, it's simply an initialized application object instance.

Facing issues in Backbone With Rails 3.x, for multiple routers

In one of the rails app I am trying to use backbone with "rails-backbone" gem,
And I have created one model using scaffolding which is working fine.
but I have another model and I am trying to use different router for it, but when tries to instantiate that router from index.html.erb it fires,
"Uncaught TypeError: undefined is not a function" which clearly means there is no such router. But it is there and even in developer's tool it shows those JS files. I tried all different ways but it didn't work. Thanks in advance.
I'd guess that you're defining your router like this:
class SomeRouter extends Backbone.Router
# router code goes here
and then you're trying to create one with:
r = new SomeRouter
But CoffeeScript will wrap your files in a function to prevent scope creep:
Although suppressed within this documentation for clarity, all CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult to pollute the global namespace by accident.
If you'd like to create top-level variables for other scripts to use, attach them as properties on window, or on the exports object in CommonJS. The existential operator (covered below), gives you a reliable way to figure out where to add them; if you're targeting both CommonJS and the browser: exports ? this
That wrapper will hide SomeRouter inside a function so there will be no SomeRouter visible outside the file which defines it.
A common solution in Rails/Backbone apps is to manage the namespaces yourself. Set up your own namespace somewhere before any other (Java|Coffee)Script will be pulled in:
# AppName is just a placeholder, you'd use something more
# sensible in real life.
window.AppName =
Routers: { }
Views: { }
Models: { }
Collections: { }
and then define your router as:
class AppName.Routers.SomeRouter extends Backbone.Router
#...
and later:
r = new AppName.Routers.SomeRouter
similarly with models, collections, and views that need to be globally visible.

Global 'cache' variables in a requireJS AMD application

My application has a View() model that fetches HTML, CSS, etc. with a simple call to a view path. As many of these views and viewlets are shared or required multiple times I'd like to maintain a 'cache' object of loaded views that any new instance of a View() can check and read from if that particular view has been loaded.
In a requireJS implementation, any ideas on where is best to put this view 'cache' object? Ideally I'd like to have something like a Session() object that contains it, and I'd be able to reference a single instance of Session() from anywhere in my app.
Any thoughts on best practices for this?
Many thanks!
I suggest you to use a Singleton approach creating a simple module for this case. For instance, you could create a module like this:
define(["mydep","myotherdep"], function(dep1,dep2){
var Hellovariable = {
"attr1": ...,
"attr2": ...,
...
"attrN": ...
}
return Hellovariable;
});
When you call this module using AMD you will only have an unique instance for this variable and its attributes.

Structing a backbone.js application

I have a backbone.js application with multiple models, views, collections and templates (in a script tag with type text/template with an ID which the views use to load the template in using _.template($(id).html())).
Currently, all of the above are in a single file, which makes it quite ugly. This is an offline application (i.e, its loaded from the local filesystem and talks to a web server which allows cross-origin requests). I've been trying to figure out how to move the views, models and templates to separate files, I tried just moving the views and models out to views.js and models.js, but the views depend on the templates, and the templates can't be put into views.js (as its a JS file, and therefore can't have script tags..).
My only solution at this point seems to be moving the templates into global variables, which would be fine except for the javascript string escaping/multi line strings that would be required..
How is this usually handled?
Thanks!
Use RequireJS to package your views and models up into modules, and RequireJS will take care of the dependency resolution for you. You can get down to one view or model per file that way, too, instead of putting them all in one views.js or models.js.
Then, use the text! plugin to store your templates in text files, and require them like normal modules.
define(function (require, exports, module) {
var templateText = require("text!./person.tmpl");
var $ = require("jquery");
exports.PersonView = Backbone.View.extend({
render: function () {
doStuffWith(_.template(templateText));
}
});
});
Take a look at these starter applications that use Backbone and RequireJS.
This one has Backbone.LocalStorage in it, which could help you with your offline stuff.
https://github.com/jcreamer898/Savefavs
This other one is just a simple starter for building an app...
https://github.com/jcreamer898/RequireJS-Backbone-Starter
They way you can handle templates with is...
define([
'jquery',
'backbone',
'underscore',
'models/model',
'text!templates/main.html'],
function($, Backbone, _, model, template){
var MyView = Backbone.View.extend({
initialize: function(){
this.template = _.template(template);
},
render: function(){
this.template(model);
}
});
return new MyView();
});
You might want to check out the Backbone boilerplate. This add a nice modular structure to your backbone app without polluting the global namespace, and provides a simple template caching.
It's really easy to change the template renderer to someting different that JST.
Even if the general idea can be followed without any server side requirements, the boilerplate provides a basic node.js app as well.

Categories