My app
module bootstraps a Backbone.js application.
I need app
to be available in every other view for easy access to router, triggering navigation, etc.
I never ported an app to RequireJS before, and I got stuck on circular dependency problem, and this answer isn't quite clear to me, so I'm not sure if I applied the solution correctly.
I'm using AMD sugar style throughout the app, so here's what I came up with:
app.js
define(function (require, exports) {
'use strict';
var _ = require('underscore'),
Backbone = require('backbone'),
Router = require('Router'),
AppView = require('common/views/app_view'),
// ...
return _.extend(exports, {
start: function () {
this.router = new Router();
Backbone.history.start();
this.appView = new AppView();
this.appView.render();
},
// ...
});
});
Extending exports
instead of directly returning an object allows me to do app = require('app')
in any view of the app without worrying about circular dependencies.
All other modules in the app return value normally (i.e. I'm not using exports
anywhere else).
Is this an OK strategy for a Require.js Backbone app?
Are there better solutions (that will also work with optimizer or Almond)?
An example of how I'm using app
in a (rather deeply nested) view:
zine_item_view.js
define(function (require) {
'use strict';
var View = require('common/views/view'),
Misc = require('common/helpers/misc'),
app = require('app');
var ZineItemView = View.extend({
template: 'templates/social/items/zine_item.html',
events: {
'click': 'showZine'
},
showZine: function (e) {
if (!Misc.shouldHandleClick(e)) {
return;
}
app.presenter.showZine({
zine: this.model,
route: app.router.routeToZineTrending(this.model.id)
});
}
});
return ZineItemView;
});
1 Answer 1
There are few ways to solve your problem with Backbone.js + Require.js and executing functions or changing routes from view.
1. Using Backbone.Router
Here is approach I've used multiple times:
'use strict';
// Your view --------------
define([
'jquery'
'backbone'
'common/views/view',
'common/helpers/misc'
], function (,ドル Backbone, View, Misc) {
var ZineItemView = View.extend({
...
showZine: function (e) {
if (!Misc.shouldHandleClick(e)) {
return;
}
// Pass all control from view to the router,
// see http://stackoverflow.com/a/20311253/1363799
Backbone.history.navigate('yourUrl_to_zine');
}
});
return ZineItemView;
});
// Main block --------------
require([
'jquery'
'backbone',
'app',
'ZineItemView'
], function(,ドル Backbone, App, ZineItemView) {
...
var app = new App();
var zineItemView = new ZineItemView({...});
// Router way
var router = Backbone.Router.extend({
routes: {
"yourUrl_to_zine": "showZine"
},
showZine: function() {
// Here you gave access to zineItemView.model and zineItemView.model.id
app.presenter.showZine({
zine: zineItemView.model,
// I think next row becames obsolete
route: app.router.routeToZineTrending(zineItemView.model.id)
});
}
});
});
2. Event-driven approach
'use strict';
// Your view --------------
define([
'jquery',
'backbone',
'common/views/view',
'common/helpers/misc'
], function (,ドル Backbone, View, Misc) {
var ZineItemView = View.extend({
...
showZine: function (e) {
if (!Misc.shouldHandleClick(e)) {
return;
}
var view = this;
// Trigger global event with desired parameters
$(window).trigger('showZine.App', {
zine: view.model,
modelId: view.model.id // probably it's obsolete, because you can get it from zine property
});
}
});
return ZineItemView;
});
// Somewhere in app block --------------
// lodash is a dependency, because we use bind method
var App = {
initialize: function() {
$(window).on('showZine.App', _.bind(this.presenter.showZine, this) );
},
presenter: {
showZine: function(event, paramsObj) {
// Here you have paramsObj,
// with paramsObj.zine = zineItemView.model
// and paramsObj.modelId = zineItemView.model.id
// Call app.router.routeToZineTrending from here, but be aware about value of `this` and `app` variables
}
}
};
3. Syntax of module defining (optional)
It preferentual, but seems to be a standart (it's easier to see dependencies):
'use strict';
define([
'common/views/view',
'common/helpers/misc',
'app'
], function (View, Misc, app) {
var ZineItemView = View.extend({
...
});
return ZineItemView;
});
-
\$\begingroup\$ You are welcome :). I'm also looking for more robust solution which somebody could propose. \$\endgroup\$terales– terales2014年04月07日 12:19:21 +00:00Commented Apr 7, 2014 at 12:19
Explore related questions
See similar questions with these tags.
app
? \$\endgroup\$app.presenter.showZine
supposed to do here ? Are you setting a route inside of aView
? \$\endgroup\$presenter
is not a view, it's a separate object that has methods likeshowZine
,showUser
,showHome
, etc. Think of it as of a simple "controller" (although there are no controllers in Backbone per se). It manages the root view. It often needs to load a model asynchronously, and, when it is ready, updates both root view and the current route. \$\endgroup\$