Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable UI-Router Interaction with window.location

This is a long shot, but UI-router is so popular, thought maybe someone here would have insight on this issue.

I'm migrating a project to Angular JS. The project consists of a page with several different panels - each of which is downloaded from the server as HTML with AJAX, injected into the page with Javascript, and associated with its own href, which managed by jQuery History.

jQuery history tracked the browser states and updated the window.href accordingly after each panel was injected with Javascript. For instance:

Panel 1:
  window.location.href // http://myapp.com/panel1
  History.getLocationHref() // http://myapp.com/panel1
  History.getPageUrl() // http://myapp.com/panel1
Panel 2:
  window.location.href // http://myapp.com/panel2
  History.getLocationHref() // http://myapp.com/panel2
  History.getPageUrl() // http://myapp.com/panel2
Panel 3:
  window.location.href // http://myapp.com/panel3
  History.getLocationHref() // http://myapp.com/panel3
  History.getPageUrl() // http://myapp.com/panel3

etc, etc.

Because each of these panels are injected, rather than compiling them with Angular after injection into the DOM, I'm bootstrapping separate AngularJs Apps for each of them. This has worked fine up until now.

Now I'm using AngularJs UI-router in Panel 2 - so I can render data in alternative templates. The problem is, UI-Router must somehow mess with browser history and/or window href. Because once that app is instantiated, let's say I start at Panel 1, then click Panel 2, then click Panel 3, I have this problem:

Panel 1:
  window.location.href // http://myapp.com/panel1
  History.getLocationHref() // http://myapp.com/panel1
  History.getPageUrl() // http://myapp.com/panel1
Panel 2:
  window.location.href // http://myapp.com/panel2
  History.getLocationHref() // http://myapp.com/panel2
  History.getPageUrl() // http://myapp.com/panel2
Panel 3:
  window.location.href // http://myapp.com/panel2
  History.getLocationHref() // http://myapp.com/panel2
  History.getPageUrl() // http://myapp.com/panel3

basically, once UI-Router is instantiated with an app, jQuery History no longer works, and the location href persists at the URL of the ui-router app.

Is there anything I can do to disable ui-router's interaction with the window's location href? Or is integral to how the module works?

Here's my panel2.states.js file if it helps:

angular.module("panel2")
.config(["$stateProvider", function($stateProvider) {
  $stateProvider
    .state('table', {
      views: {
        index: {
 //             controller: "TableController as at",
            templateUrl: "table.html"
        }
      }
    })
    .state('tiles', {
      views: {
        index: {
//              controller: "TilesController as tc",
            templateUrl: "tiles.html"
        }
      }
    });
}]);

Update (4/27/2015)

I solved my particular issue by just getting rid of jQuery History and the features it adds beyond what we need. Instead I just interact directly with window.history:

 window.history.pushState({panel: "panel3"}, 
    document.title + " | " + 'panel3', 
    window.location.href + "/panel3");

I'm still curious as to what was causing this interaction and if angular or angular ui-router directly interacts with window.location?

like image 556
Eric H. Avatar asked Apr 24 '15 19:04

Eric H.


1 Answers

Angular exposes the $location service to interact with the window.location object and I'm pretty sure ui-router uses that and not the window.location object directly. You can decorate the $location service from your config function to intercept all calls to the $location service and provide your own implementation that does not use window.location.

e.g. (highly simplified):

$provide.decorate('$location', function($delegate) {
    var currentUrl = '';
    //we base the proxy on the original
    var locationProxy = Object.create($delegate);
    //and overwrite what we need
    locationProxy.url = function(newUrl) {
        if (newUrl) {
            $rootScope.$broadcast('$locationChangeStart' /* other event args here*/);
            currentUrl = newUrl;
            $rootScope.$broadcast('$locationChangeSuccess' /* other args here */);
        } else {
            return currentUrl;
        }
    };

});

It does require you to implement all functions in a compatible way with the original $location service, so it will probably be quite a bit of work.

like image 168
Tiddo Avatar answered Nov 06 '22 02:11

Tiddo