I am trying to achive something like this in backbone js
var AppRouter = Backbone.Router.extend({
routes: {
// MVC like route
':controller': 'defaultRoute',
// MVC like route
':controller/:action': 'defaultRoute',
// MVC like route
':controller/:action/:id': 'defaultRoute',
// MVC like route
':controller/:action/*id': 'defaultRoute'
},
defaultRoute: function (controller, action, id) {
// render view here or
// call another specific route regarding to controller parameter
}
});
var appRouter = new AppRouter;
Backbone.history.start();
So when url is: something.com/#home/index defaultRoute function will get parameters controller="home" and action="index".
I am wondering now how to find view (Backbone.View) in folder "controller/home/index" and instantiate dynamically (and render). Also wondering if better approach would be to have Backbone.Router for each "controller" (I am using name "controller" but it is actually "router").
Any ideas?
UPDATE with possible solution!
I ended up with this
// Filename: router.js
define([
'jquery',
'underscore',
'backbone'
], function ($, _, Backbone) {
var AppRouter = Backbone.Router.extend({
routes: {
// MVC like route
':controller': 'defaultRoute',
// MVC like route
':controller/:action': 'defaultRoute',
// MVC like route
':controller/:action/:id': 'defaultRoute',
// MVC like route
':controller/:action/*id': 'defaultRoute'
},
defaultRoute: function (controllerName, actionName, id) {
controllerName = controllerName || Config.Defaults.Controller;
actionName = actionName || Config.Defaults.Action;
require(["controllers/" + controllerName], function (ctl) {
var code = "ctl." + actionName + "();";
eval(code);
});
}
});
var appRouter = new AppRouter;
Backbone.history.start();
});
And sample controller is this
define([
'jquery',
'underscore',
'backbone'
], function ($, _, Backbone) {
return {
index: function () {
console.log("Action: Index");
},
about: function () {
console.log("Action: About");
}
};
});
It works with this sample. Now trying to solve params binding etc. Need more testing.
At this time I am still investigating but here is the code I am using at the moment:
// Filename: router.js
define([
'jquery',
'underscore',
'backbone'
], function ($, _, Backbone) {
var AppRouter = Backbone.Router.extend({
routes: {
// MVC like route
':controller': 'defaultRoute',
// MVC like route
':controller/:action': 'defaultRoute',
// MVC like route
':controller/:action/:id': 'defaultRoute',
// MVC like route
':controller/:action/*id': 'defaultRoute'
},
defaultRoute: function (controllerName, actionName, id) {
controllerName = controllerName || Config.Defaults.Controller;
actionName = actionName || Config.Defaults.Action;
require(["controllers/" + controllerName], function (ctl) {
var code = "ctl." + actionName + "();";
eval(code);
});
}
});
var appRouter = new AppRouter;
Backbone.history.start();
});
So "controller" looks like
// Filename: controllers/home.js
define([
'jquery',
'underscore',
'backbone',
], function ($, _, Backbone) {
return {
index: function () {
require(['views/home/index'], function (view) {
view.render();
});
},
about: function () {
require(['views/home/about'], function (view) {
view.render();
});
}
};
});
Next is to create typical backbone views.
I will post more when I test passing parameters and do some more complicated tests.
JS client side dynamic dependency loading, I think this is still in our dreams.
You can play with very tricky technics like Dynamic Script Loading but even if it looks easy at the beginning it is gonna become in a nightmare (sooner or later).
If you need a technic like this be sure it worths it, you should try to think it again.
About if to use one Router for the whole application or separate it in several Routers by controllers/modules or whatever I have already said my opinion about.
Related
Backbone version 1.1.2
Require version 2.0.2
//My main file
require.config({
paths: {
jquery: 'assets/js/libs/jquery/jquery-1.9.1.min',
underscore: 'assets/js/libs/underscore/underscore-min',
backbone: 'assets/js/libs/backbone/backbone-min',
bootstrap: 'assets/js/libs/bootstrap/bootstrap.min',
text : 'assets/js/libs/require/text',
mustache: 'assets/js/libs/mustache/mustache'
},
shim: {
'backbone': {
deps: ['jquery','underscore'],
exports: 'Backbone'
},
'bootstrap': {
deps: ['jquery']
}
}
});
require([
// Load our app module and pass it to our definition function
'assets/js/app',
], function(App){
App.initialize();
});
//My App file
define([
'jquery',
'underscore',
'backbone',
'assets/js/router'
], function($, _, Backbone, Router){
var initialize = function(){
Router.initialize();
}
return {
initialize: initialize
};
});
//My Router File
define([
'jquery',
'underscore',
'backbone',
'assets/js/views/trabajadores/list'
], function($, _, Backbone, TrabajadoresListView){
var AppRouter = Backbone.Router.extend({
routes:{
'':'mostrarTrabajadores',
'trabajadores': 'mostrarTrabajadores'
},
mostrarTrabajadores: function(){
var trabajadoresListView = new TrabajadoresListView();
trabajadoresListView.render();
}
});
var initialize = function(){
var app_router = new AppRouter;
Backbone.history.start();
};
return {
initialize: initialize
};
});
I'm a inspection the code and when the following code line executes "var app_router = new AppRouter; ", the console says: Uncaught TypeError: undefined is not a function.
The Router it's not working for me.why?
You can declare your route actions inside the initialize method. Just use the following:
var initialize = function(){
var app_router = new AppRouter;
app_router.on('route:index', function() {
console.log('index route');
});
return {
initialize: initialize
};
});
Just make sure you follow the format "route:Action" in the Router's 'on()' method.
I am preparing a boiler Angular Application that will use AMD (require.js). So far I got it working, but I have issues with services. How do I incorporate service?
This is Main.js:
require.config({
paths: {
// These are the core components - without which our application could not run
angular: '../lib/angular/angular',
angularResource: '../lib/angular/angular-resource',
// These are components that extend our core components
jquery: '../lib/jquery/jquery-1.8.2.min',
bootstrap: '../lib/bootstrap/js/bootstrap',
underscore: '../lib/underscore/underscore',
text: '../lib/require/text'
},
shim: {
'angular' : {'exports' : 'angular'},
'angular-resource' : {deps:['angular']},
'bootstrap': {deps:['jquery']},
'underscore': {exports: '_'}
},
priority: [
"angular"
],
urlArgs: 'v=1.1'
});
require( [
'angular',
'app',
'services/services',
'services/dateGetter',
'controllers/controllers',
'controllers/navbar',
'controllers/exampleTemplateController',
'filters/filters',
'directives/directives',
'routes'
], function(angular, app) {
angular.element(document).ready(function () {
angular.bootstrap(document, ['myApp']);
});
});
This is how I developed controller:
define([
'app',
'../helpers/exampleFile' //example of importing custom file.js in our controller.
],
function(app, exampleFile) {
'use strict';
return app.controller('exampleTemplateController', [
'$scope', 'dateGetter',
function ($scope ) {
$scope.sayHello = function(module) {
alert("Current Date: " + dateGetter.getCustomDate + " " + exampleFile(module.name));
}
}
]);
});
This is how I tried to develop service (failing miserably here):
define([
'app'
],
function(app) {
'use strict';
debugger;
return app.factory('dateGetter', [
'$scope',
function ($scope ) {
$scope.getCustomName = function() {
return "THIS IS MY NAME";
}
}
]);
});
I think I am close, but something eludes me.
Another question is, if I end up with lots of controllers and services, and we will... do I need to list each and everyone in main.js file (under require:)?
I got the service working now. It was my fault. Here it is now, and I can access it and use it.
define([
'app'
],
function(app) {
return app.factory('serviceExample', function ( ) {
return {
nameOfMethod: function () {
return "Is this working";
}
}
}
);
});
What I wonder now... Do I need to use required with Angular at all?
I have read many posts debating the same question, without concise answer.
I was thinking to use require, since we used it before, and this application will grow to be a large bugger anyway.
Opinions?
I'm trying to follow Organizing your application using Modules (require.js I'm struggling to understand how routing works.
I cannot get simple binding to work for index:
// Filename: router.js
define([
'jquery',
'underscore',
'backbone',
'views/projects/list'
], function ($, _, Backbone, ProjectListView) {
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'': 'index'
}
});
var initialize = function () {
var app_router = new AppRouter();
app_router.on('index', function () {
alert("index"); // this never gets called
});
Backbone.history.start();
return app_router;
};
return {
initialize: initialize
};
});
When page is loaded nothing happens. This however works:
// Filename: router.js
define([
'jquery',
'underscore',
'backbone',
'views/projects/list'
], function ($, _, Backbone, ProjectListView) {
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'': 'index'
},
index: function() { alert("works"); }
});
var initialize = function () {
var app_router = new AppRouter;
Backbone.history.start();
return app_router;
};
return {
initialize: initialize
};
});
Am I missing something?
Ok, so this is how it's done:
var initialize = function () {
var app_router = new AppRouter();
app_router.on("route:index", function () {
alert("hello world");
});
Backbone.history.start();
return app_router;
};
I've been trying to practice on backbone.js, I found one tutorial online which I was trying to follow (http://backbonetutorials.com/what-is-a-router/) but unfortunately i have problem reaching to my view through the router.
Below is my code
main.js
requirejs.config({
// create local alias for package
paths: {
l : 'my/vehicle',
underscore : 'vendors/underscore',
jqueryui : 'vendors/jquery-ui/js/jquery-ui-1.9.0.custom.min',
backbone : 'vendors/backbone',
bootstrap : 'vendors/bootstrap'
},
shim: {
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
underscore: {
exports: "_"
}
}
})
require(['../../config'], function(core){
require(["l/app"], function(App) {
'use strict';
App.initialize();
});
});
app.js
define(["jquery", "backbone", "l/router"], function($, Backbone, Router) {
var initialize = function(){
// Pass in our Router module and call it's initialize function
Router.initialize();
}
return {
initialize: initialize
};
});
router.js
define([
'jquery',
'underscore',
'backbone',
'l/views/BrowseVehicle'
], function($, _, Backbone, BrowseVehicleView){
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'/browse' : 'showVehicleBrowse',
// Default
'*actions' : 'defaultAction'
}
});
var initialize = function(){
var app_router = new AppRouter;
app_router.on('showVehicleBrowse', function(){
// Call render on the module we loaded in via the dependency array
console.log('am here');
var BrowseVehicleView = new BrowseVehicleView();
BrowseVehicleView.render();
});
app_router.on('defaultAction', function(actions){
// We have no matching route, lets just log what the URL was
console.log('No route:', actions);
});
Backbone.history.start();
};
return {
initialize: initialize
};
});
views/BrowseVehicle.js
define([
'jquery',
'underscore',
'backbone'
], function($, _, Backbone){
var BrowseVehicleView = Backbone.View.extend({
el: $('#vehicle-browse-form'),
render: function(){
// Using Underscore we can compile our template with data
console.log('I reached vehicle browse form');
}
});
// Our module now returns our view
return BrowseVehicleView;
});
There is no error on loading the code, console.log is not printing anything in the view nor in the router inside the routed function. I tried to access my urls using URL/#/browse but not getting the console.log statement.
Can anyone please advise?
In the routes {} definition remove the forward slash in front of browse.
Let's say my app works but I love to learn and to find the best way of doing things.
I really appreciate this post about Reducing Backbone Routers To Nothing More Than Configuration.
And the following bbclonemail which is not using requires.
Actually my implementation is a monolithic block (app.js, router.js).
Here's my questions:
1) What should the router module router.js return?
2) How should I remove The Callback Functions from router.js ?
3) What should the app module app.js return?
4) How should I decouple the app.js in many others apps (for example: main, tasks, projects)
app.js
// app.js
define([
'router'
// some modules
],
function (router, Backbone, HeaderView)
{
"use strict";
var myApp = new Backbone.Marionette.Application();
myApp.addRegions({
header: '#header',
sidebar: '#sidebar',
mainColumn: '#main-column',
rightColumn: '#right-column'
});
myApp.initHeader = function () {
var headerView = new HeaderView();
myApp.header.show(headerView);
}
// many others many views
myApp.start();
myApp.initialize = function() {
router.initialize();
Backbone.history.start();
}
return myApp;
});
router.js
// router.js
define([
// some modules
],
function (Backbone)
{
"use strict";
var AppRouter = Backbone.Marionette.AppRouter.extend({
routes: {
tasks: 'tasks',
projects: 'projects',
// many others keys/values
'*defaults': 'home'
},
getApp: function ()
{
var mainApp;
require(['js/app'], function (app) {
mainApp = app;
});
return mainApp;
},
home: function()
{
var app = this.getApp();
app.initHeader();
app.initSidebar();
app.initTaskDetails();
},
// many others callbacks
});
var initialize = function() {
new AppRouter;
};
return {
initialize: initialize
};
});
For the Router part you should make like this:
router.js
// router.js
define([
'rooterController'
// some modules
],
function (Backbone, rooterController)
{
"use strict";
var AppRouter = Backbone.Marionette.AppRouter.extend({
routes: {
tasks: 'tasks',
projects: 'projects',
// many others keys/values
'*defaults': 'home'
}
});
return new AppRouter({constroller: rooterController})
});