Backbone.js and Browserify - requiring same module multiple times - javascript

I am currently working on a Backbone JS application, and I started using Browserify for the first time. But of course I ran into a few problematics. This is one of them.
I have the following module, /js/views/Home.js.
var $ = require('jquery'),
_ = require('underscore'),
Backbone = require('backbone');
Backbone.$ = $;
module.exports = Backbone.View.extend({
el: '#view',
template: _.template($('#home-template').html()),
initialize: function () {
this.render();
},
render: function () {
this.$el.html(this.template());
},
events: {
'click button': 'searchSubmit'
},
searchSubmit: function () {
// this should be where the magic happens
}
});
When the searchSubmit method is called, I want to do something like router.navigate('search').
My question: If I have a router module, Router.js, do I then need to create a new instance of it in all of my modules every time I want some router functionality?
var Router = require('./Router.js'),
router = new Router();
It just does not seem logical to create a new router in every view, when Browserify bundles them all together.
Is it me who do not understand Browserify properly, and is there a more clever solution? Thanks!

When you call
var Router = require('./Router.js');
Browserify is actually keeping track of a single instance of Router, so it is not a new instance every time. Think of it as a reference or using statement. See this SO post for more details.
But with router = new Router(); you run into a problem of your router being instanced. I suggest that in Router.js you export an instance of your router.

Related

How do I use Jitsi Meet in an EmberJS app

In my Ember app I'm using ember-inject-script which I installed:
npm install --save-dev ember-inject-script
The controller.js file for my page looks like this:
import Ember from 'ember';
import injectScript from 'ember-inject-script';
export default Ember.Controller.extend({
init: function() {
this._super();
var url = "https://meet.jit.si/external_api.js";
injectScript(url);
var domain = "meet.jit.si";
var room = "JitsiMeetAPIExample";
var width = 700;
var height = 700;
var htmlElement = document.querySelector('#meet');
var api = new JitsiMeetExternalAPI(domain, room, width, height,
htmlElement);
}
});
The Template is this:
<h2>Jitsi Meet</h2>
<div id="meet"></div>
{{outlet}}
Yet I get a console error:
Error while processing route: projects.index JitsiMeetExternalAPI is not defined ReferenceError: JitsiMeetExternalAPI is not defined
injectScript in asynchronous so you can't use JitsiMeetExternalAPI very next statement. You need to use then.
Another issue is, you are accessing the DOM element in controller init method, which will not be available. generally controller is not DOM aware. for this I will encourage you to write Component and use didInsertElement hook
One more alternative approach to load js at the required time, is in routes beforeModel hook, you can just use Ember.$.getJSON(url).
beforeModel(){
return Ember.$.getJSON(url);
}

require.js loop in marionette app

I'm starting a marionette app and I try to structure it. So now I have:
define(["marionette", "handlebars", "routes"], function(Marionette, Handlebars, Route){
var App = new Marionette.Application();
...
App.addRegions({
header: "#header_region",
...
});
App.addInitializer(function(options){
...
new Route();
Backbone.history.start();
});
return App;
});
and my routes looks like:
define(["marionette", "app", "header/view"], function(Marionette, App, headerView){
var Route = Backbone.Marionette.AppRouter.extend({
routes : {
'' : 'home'
},
home: function(){
var header_view = new headerView();
App.header.show(header_view);
...
}
});
return Route;
});
Obviously I have a loop in dependencies here with App.header.show(header_view). What is the common way to solve it? How do you structure your Marionette app?
This was a great example that helped to get me going when building my first Marionette App: https://github.com/BoilerplateMVC/Marionette-Require-Boilerplate/tree/master/public/js/app
The way you currently have your route file set up is the backbone way of doing it. You should create a Marionette Controller that will respond to the App routes.
Also, you'll see that this person creates init files to specify all of the start up logic (specifying global static variables and instantiating the controller and router to be used).
Hope this helps!

My backbone js router isn't working

I am just starting to learn backbone js. I am not understanding the router. I have written a simple code. What it should do is to print 'I am working' in the console. But it is not working.
$(document).ready(function(){
var AppView = Backbone.View.extend({
el: 'body',
initialize: function(){
console.log('this is working');
}
});
var AppRouter = Backbone.Router.extend({
routes: {
'': function(){
var a = new AppView();
}
}
});
var ar = new AppRouter();
Backbone.history.start();
});
You almost certainly have a Backbone version problem. The 1.0.0 Change Log entry says:
The routes in a Router's route map may now be function literals, instead of references to methods, if you like.
And you can even find the trivial one line change in the revision history that made this new behavior possible.
Older versions of Backbone wanted route method names in routes and didn't know what to do with functions. Upgrade to the most recent Backbone (and Underscore and jQuery) and your code will work.
Demo: http://jsfiddle.net/ambiguous/sfeCr/1/

Emberjs Router with requirejs

When building a relatively large application, how should I define my router? More specifically, if using requirejs I have the following code:
main.js
define('application',['routes/app_router'], function(router){
return Ember.Appcliation.create(
LOG_TRANSITIONS:true,
...
});
requirejs('application',function(application){
var App = window.App = application;
...
}
and in the routes/ I have app_router.js
define('app_router',['ember'],function(){
...
});
So should I pass an app to my app_router to set the App.Router.map... method or should I return a Ember.Router.map(...)? If the first variant is chosen then for sure, the dependencies change.
In other words, should I create an "empty" Ember.Application and pass it to the router so it can define the App.Route.map(... method, since it has reference to this, like this.route\this.resource..., or should I invoke Ember.Router.create() then invoke the map function on it, then return this from the module and set it to App.Router = router.
So should I pass an app to my app_router to set the App.Router.map... method or should I return a Ember.Router.map(...)? If the first variant is chosen then for sure, the dependencies change.
I'd go with the 2nd variant.
In other words, should I create an "empty" Ember.Application and pass it to the router so it can define the App.Route.map(... method, since it has reference to this, like this.route\this.resource..., or should I invoke Ember.Router.create() then invoke the map function on it, then return this from the module and set it to App.Router = router.
Neither. You should let ember create the router itself. All your code should be doing is calling App.Router's map fx. I'm no require.js expert, but something like this should work:
//Define a fx that specifies your applications routes
define('routes',['ember'], function(){
return function() {
this.route("about");
}
});
// Pass that custom routes fx to App.Router.map before routing begins
define('application',['routes'], function(routes){
return Ember.Application.create({
LOG_TRANSITIONS: true,
ready: function() {
this.Router.map(routes);
}
});
Here's a jsfiddle showing the basic concept, without require.js of course.

Accessing the return value of a require.js callback

I have a module like the following defined in one file
define(['mod1', 'mod2'], function (mod1, mod2) {
var IndexView = Backbone.View.extend({
...
});
return new IndexView;
});
And this is required from within another file (my Backbone router file) with the following
require(['src/views/index']);
Can I make the returned IndexView object accessible from within the router's scope without resorting to storing a reference in my app's namespace?
Passing around instances of Backbone views/models with require.js will quickly make your life very unhappy. It would be much easier to make your modules only return the definitions of the views/models, that way can instantiate them all inside the same scope.
So if you make your view module return just the definition:
// IndexView module
define(['dep1', 'dep2'], function (dep1, dep2) {
var IndexView = Backbone.View.extend({
...
});
return IndexView;
});
You can then instantiate it inside your router:
// our main requirejs function
requirejs(['path/to/indexview'], function (IndexView) {
var AppRouter = Backbone.Router.extend({
initialize: function () {
// bind our IndexView to the router
this.IndexView = new IndexView();
}
});
// start the app
var app = new AppRouter();
});
That way your code is still modular with Require.js, but you can pass around the router's scope using this.

Categories