I have my application set up in the following way. It does not allow me to trigger any "java-script routes"- after loading the page-- after I navigate to this page with a sub-domain extension to the url I enter.
//Create App
App = new Backbone.Marionette.Application();
//APP Regions
App.addRegions({
displayRegion: "#displayRegion"
});
//Routing controller
someController = {
usersarea: function () {
App.displayRegion.show(userList_ITEM);
alert('Users');
},
login: function () {
App.displayRegion.show(login_view);
alert('Login View');
}
};
//Router
MyRouter = new Marionette.AppRouter({
controller: someController,
appRoutes: {
"users": "usersarea",
"login": "login",
}
});//MyRouter
// Application Views
userList_ITEM_proto = Backbone.Marionette.ItemView.extend({
template: "#userList_ITEM"
});
login_view_proto = Backbone.Marionette.ItemView.extend({
template: "#login_view"
});
//Before STARTS
App.on('initialize:before', function () {
if (!Backbone.History.started) Backbone.history.start();
alert('It works');
login_view = new login_view_proto;
userList_ITEM = new userList_ITEM_proto;
});
//After START
App.on('initialize:after', function (options) {
console.log('Initialization Finished');
});
//At Start
App.on('start', function (options) {
alert('It works');
});
App.start();
You're trying to use view instances in someController before you've instantiated them.
http://jsfiddle.net/ddL4n/28/
You have a number of dependency issues in this script and should consider using Marionette's modules or Require.js to manage them.
Related
I have an Angular js module
var appModule = angular.module('appModule', ['datatables','ngMaterial', 'ui.select'])
when i declare a new component using my appModule, I refresh my app in browser but it creates a request load cycle in XHR and my app breaks
appModule.component('myCustomTable', {
templateUrl: 'table-component',
controller: function () {
this.user = {
name: 'user name'
};
}
});
Am using AngularJS 1.65
It might happen because your controller is an anonymous function.
(According to: https://docs.angularjs.org/tutorial/step_03)
appModule.component('myCustomTable', {
templateUrl: 'table-component',
controller: function () { // <- Here
this.user = {
name: 'user name'
};
}
});
my code of module is.
spine.module('communityApp', {
startWithParent: false,
define: function (communityApp, App, Backbone, Marionette, $, _) {
console.log("communityApp.js");
// Setup the router for this module
var Router = Marionette.AppRouter.extend({
before: function () {
console.log("communityApp.js: router.before()")
App.startSubApp("communityApp", {});
},
appRoutes: {
"community": "showCommunityTab",
"community/pforum": "getPforum",
"community/questions":"getQuestions",
"community/events": "getEvents"
}
});
// Startup router
App.addInitializer(function () {
console.log("communityApp.js: App.addInitializer()")
// contains active controller
communityApp.activeController = new communityApp.Controllers.tabController();
// initializing route
communityApp.Router = new Router({
controller: communityApp.activeController
});
});
// Let app know we started
communityApp.addInitializer(function () {
console.log("communityApp.js: DemoApp.addInitializer()");
App.vent.trigger("app:started", "communityApp");
});
// This will run when a sub app (module) starts
communityApp.on("start", function () {
console.log("communityApp.js: on 'Start'()");
});
code of controller is.
spine.module("communityApp", function (communityApp, App, Backbone, Marionette, $, _) {
"use strict";
// initializing controllers and collections for message tabs
communityApp.Controllers = {};
communityApp.Collections = {};
communityApp.Controllers.tabController = Marionette.Controller.extend({
showCommunityTab: function () {
this.getCommunityTab();
},
getCommunityTab: function (data) {
//var tabLayout = new communityApp.Views.tabLayout();
//tabLayout.render();
// creating active layout
communityApp.activeTabLayout = new communityApp.Views.tabLayout();
communityApp.activeTabLayout.render();
// loading community module view
App.regionMain.show(communityApp.activeTabLayout);
// load pforum on community module load
this.getPforum();
},
getPforum : function(){
console.log('Public Forum Tab');
var pforum = new communityApp.Controllers.pforumController();
pforum.init();
},
getQuestions : function(){
console.log('Question tab');
var questions = new communityApp.Controllers.questionsController();
questions.init();
},
getEvents : function(){
console.log('Events tab');
var events = new communityApp.Controllers.eventController();
events.init();
}
});
Code where error is, Its a tab page.
spine.module("communityApp", function (communityApp, App, Backbone, Marionette, $, _) {
"use strict";
communityApp.Controllers.pforumController = Marionette.Controller.extend({
init: function(){
var func = _.bind(this._getPforum, this);
$.when(App.request('alerts1:entities' , {origin:'pforum'}))
.then(func)
},
_getPforum:function(data){
// populating the data
communityApp.activeTabLayout.pforum.show(new communityApp.CollectionViews.pforumCollectionViews({
collection: data
}));
}
});
That's because you're creating the activeTabLayout in getCommunityTab, and you're trying to access it after creating the controller in getPforum. These are both attached to separate routes. Therefore you're not guarenteed that communityApp.activeTabLayout exists inside of your init method.
community/pforum -> creates your controller, but not your tab layout.
community -> creates your tab layout, but not your controller.
You need to make sure communityApp.activeTabLayout = new communityApp.Views.tabLayout(); runs before pforum.init();
In below code, when i want to use get() method as seen in code return undefined. what's the problem.
<script type="text/javascript">
(function() {
window.App = {
Models: {},
Views: {}
};
window.vent = _.extend({}, Backbone.Events);
})();
//Model
App.Models.User = Backbone.Model.extend({
url: '/users'
});
var user = new App.Models.User();
user.fetch({
success: function (user) {
console.log(user.get('firstname'));
}
});
</script>
That's because the value given to the success callback isn't a Backbone model, it's jsut the raw server responsse. To display the first name as soon as the data is fetched, you can use a deferred (see http://api.jquery.com/jQuery.Deferred/):
var user = new App.Models.User();
$.when(user.fetch()).done(function(){
console.log(user.get("firstname");
});
Your Example is working for me here it is http://jsfiddle.net/YYM43/
Try to see if you have loaded the libs (Backbone.js ...) correctly.
(function() {
window.App = {
Models: {},
Views: {}
};
window.vent = _.extend({}, Backbone.Events);
})();
//Model
App.Models.User = Backbone.Model.extend({
url: 'http://echo.jsontest.com/name/betty/age/22'
});
var user = new App.Models.User();
user.fetch({
success: function (user) {
console.log(user.get('age'));
}
});
I'm building an app with Backbone, Marionette and RequireJS and I'd like to run by some more experienced people if the Application startup could be refined/improved in any way.
Folder structure:
index.html
js/
collections/
libs/
backbone.js
marionette.js
require.js
...
models/
views/
app.js
init.js
router.js
Currently the app's bootstrapping is as follows.
index.html defines the requireJS entry-point as:
<script data-main="js/init" src="js/libs/require.js"></script>
init.js does the RequireJS configuration and:
require(['app'], function(App){
App.start();
});
The App module in app.js:
App = new Backbone.Marionette.Application();
App.addInitializer(function (options) {
// initialize the Router; will only setup the routes and corresponding callbacks; not history.start()
App.router = new Router();
// initialize Marionette regions
App.addRegions({
'header': '#header',
'main': '#main',
'footer': '#footer'
});
});
App.on('start', function(options) {
Backbone.history && Backbone.history.start() || console.error('No "Backbone.history" to .start()');
});
return App;
The Router module in router.js:
return Backbone.Router.extend({
routes: {
'panel/:handle': 'showPanel',
},
showPanel: function (handle) {
require(['app'], function (App) {
App.main.show(new Panel_v({userHandle: handle}));
});
}
});
Is there a way to make the Router module less convoluted? I worked out this way to solve the cyclic dependency problem formed by App->Router->App.
Any other suggestions?
I've come to this solution lately, joining up App and Router in the main.js file:
App.js
define(['marionette'], function(Marionette) {
var App;
App = new Backbone.Marionette.Application();
App.vars = {};
App.addRegions({
headerRegion: "#header-region",
mainRegion: "#main-region",
footerRegion: "#footer-region",
dialogsRegion: "#dialogs"
});
App.vent.on("routing:started", function() {
Backbone.history.start();
});
return App;
});
Router.js
define(['marionette', 'app'], function(Marionette, App) {
var appRouter, routerController;
routerController = {
showViaggi: function() {
return require(['modules/viaggi/viaggi'], function(Viaggi) {
App.Modules.viaggi = new Viaggi();
return App.Modules.viaggi.start();
});
}
};
return appRouter = Backbone.Marionette.AppRouter.extend({
appRoutes: {
'viaggi': 'showViaggi'
},
controller: routerController
});
});
And the Main.js, my initial script loaded with Require.js
define(['app', 'routers/appRouter'], function(App,appRouter) {
App.addInitializer(function() {
App.Router = new appRouter;
return App.vent.trigger("routing:started");
});
return App.start();
});
I have Backbone view. It load content (component on backbone with AJAX):
render: function () {
var self = this;
$.get('/Blog', request, function (data) {
self.$el.html(data);
model.trigger('blogContainerLoaded');
});
}
Component code:
window.App = {
init: function (options) {
var BlogModel = Backbone.Model.extend({
});
var model = new BlogModel();
var BlogController = Backbone.Router.extend({
routes: {
"": "posts",
"posts": "posts",
"posts/:postId": "post",
"posts/:postId/": "post",
},
posts: function (anchor) {
window.App.views.posts.render(anchor);
},
post: function (postId, commentId) {
window.App.views.post.render(postId, commentId);
},
});
var controller = new BlogController();
if (notLoaded) {
var views = {
posts: new PostListView({ model: model, controller: controller }),
post: new PostView({ model: model, controller: controller }),
};
this.views = views;
Backbone.history.start();
}
}
};
var PostListView = Backbone.View.extend({
el: $(".posts"),
events: {
"click .js-edit-message": "editMessage",
"click .js-open-post": "navigateToPost",
"click .js-move-post": "move"
},
editMessage: function () {
debugger;
},
navigateToPost: function () {
debugger;
},
move: function () {
debugger;
},
All html code loads with ajax.
It works, but events (clicks and other) not firing!
When I load Blog component without AJAX - events working. Please Help!
Most likely your view is instantiated before your ajax call is complete. Because ajax is asynchronous, while it does load (eventually) your code to initialize the view runs first. Thus, when your view is looking to attach the events to your DOM, the necessary elements are not present.
This would also explain why when you eliminate the ajax portion of it, the code works (it's now synchronous and the DOM is present before you initialize your view code.)
Try putting your initialization code inside the ajax callback like this: (if possible)
render: function () {
var self = this;
$.get('/Blog', request, function (data) {
self.$el.html(data);
self.blogContainer = new BlogContainerView(); // Or however you do it
});
}
Another possibility is to keep your trigger.('blogContentLoaded') then attach the events at that time. Backbone.View's delegateEvents() method might be useful in your case.
Or something of that nature. Now you're guaranteed that the DOM is available for your View object to attach events to.