Search code examples
javascriptangularjsjquery-mobilebackbone.js

angularjs 1.6 with backbone router - how to activate a controller?


We have a single-page application with a backbone router and jQueryMobile, quite simple setup. Now there are two pages with angularjs in that application. But, because we are not using an angularjs router so far, both two controllers start immediately when the page is loaded (although nobody wants them to be active at that point). How can this be prevented?

So far we "bootstrap" the whole angularjs part (two controllers) when everything is loaded:

var checkinApp = angular.module('checkinApp', ['ngGeolocation']);

The main idea behind using the backbone router was to get parameter passing via the URL which is a high improvement to what jQM provides. So I would also like to pass parameters via Backbone to the angularJS pages and that would be easy with DOM attributes. However, I would like to tell the divs with the angularjs pages when they are active (and then ready these DOM attributes).


Solution

  • Thanks to the comments of JeanJaques I finally found a solution... I somehow hate it but it is much better than what I had before:

    • All "pages" stay in the index.html, they have their ng-controllers annotated.
    • An element is added to index.html (but will never be used).

    This has the advantage that jQM does all the "enhancing" when the page is loaded initially. For jQM nothing changes. Now the routing:

    • Backbone does the page switching (same for angular and "plain JS pages):

      /* global Backbone, ContactsApp */
      
      // Extends Backbone.Router
      var ContactsRouter = Backbone.Router.extend({
      
          // The Router constructor
          initialize: function () {
              // Tells Backbone to start watching for hashchange events
              Backbone.history.start();
          },
      
          // Backbone.js Routes
          routes: {
              "!/checkin_meeting_overview": "checkin_meeting_overview"
          },
      
          checkin_meeting_overview: function () {
              $("body").pagecontainer("change", "#checkin_meeting_overview", {reverse: false, changeHash: false});
          },
      
      });
      
    • Also I have ui.router configured (no idea why I initially tried ngRouter) to "enable" the correct controller if one should be called and, this is quite important, an otherwise state which is executed when angularjs is not active:

      checkinApp.config(function ($stateProvider) {
          var checkin_meeting_overview = {
              name: 'checkin_meeting_overview',
              url: '/checkin_meeting_overview',
              controller: 'meetingOverviewController',
              template: ' ',
              onEnter: function () {
                  alert("IMPORTANT Entering checkin_meeting_overview: ");
              }
          };
      
          $stateProvider.state(checkin_meeting_overview);
      
          $stateProvider.state("otherwise", {
              url: "*path",
              template: " ",
              onEnter: function () {
                  // alert("IMPORTANT Unhandled AngularJS state ");
              }
          });
      });
      

    So far this seems to work... Again thanks, JeanJaques!

    I ended up with loading the whole block including the ng-controller="..." definition and inserting it into the dom, then the controller was executed. This was done by Backbone router. All parameters were added by backbone router into the DOM as data attributes and loaded in angularjs from the DOM (in the controller).

    This is the router code to load one of the angularjs pages:

        checkin_add_meeting: function (contact_id) {
            // alert("Navigating to checkin_add_meeting with contact_id=" + contact_id + " => ANGULARJS!");
    
            var templateUrl = "js/pages/checkin/checkin_edit.html";
            var pageSelector = "#checkin_add_meeting";
    
            // Remove old page
            if ($(pageSelector).length > 0) {
                $(pageSelector).remove();
            }
    
            $.mobile.loadPage(templateUrl, {type: "get"}).done(function (e, ui, page) {
                // Hand over parameters
                $(pageSelector).data("contact_id", contact_id);
                $(pageSelector).data("talk_id", undefined);
    
                // Change pagecontainer
                $("body").pagecontainer("change", pageSelector, {reverse: false, changeHash: false});
    
                // Bootstrap angularjs
                angular.bootstrap(document.getElementById("checkin_add_meeting"), ['checkinApp']);
            }).fail(function () {
                error("ERROR: Failed loading page " + pageSelector);
            });
        },