0

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).

Ralf Jahr
  • 312
  • 2
  • 18
  • 2
    Why you are not using the default AngularJS routing (`ngRoute`) ? Which allows you also to retrieve parameters in the URL. – JeanJacques Sep 11 '17 at 12:59
  • Tried it... right now my URLs look like this: http://localhost/index.html#edit_contact/4711 What happens is that ngRoute just by including it changes the hash parts and I did not see a pattern behind this yet... Moving to http://localhost/index.html#!/edit_contact/4711 or whatever necessary would still be an option. You suggest having both routers (backbone and ngRoute) set up, correct? backbone would then switch to the correct div and ngRoute would start the controller? – Ralf Jahr Sep 11 '17 at 13:43
  • 2
    No I suggest you to use only `ngRoute`. Because I can't find any sources explaining if it's possible to use backbone routing with an AngularJS app, so I think it's not possible or not useful. So I was wondering why you are not using the default AngularJS routing ? ^^ Or if you need a more complete routing module, you can check [ui-router](https://github.com/angular-ui/ui-router). And if the problem is about the `#` take a look a [this](https://stackoverflow.com/a/41461312/6712896) – JeanJacques Sep 11 '17 at 14:05

1 Answers1

0

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);
        });
    },
Ralf Jahr
  • 312
  • 2
  • 18