8

Short version of my question is: How do I change the URL without need to trigger route change or without need to run all the controllers on the currently displayed page?

Details:

I have a template which is displayed inside the <ng-view> that has regions governed by 3 controllers. On the very top of the page I have an interactive map. When you click on the regions it broadcasts a click and other component picks up on it and displays data about this region. Really simple setup.

What I would like to do is allow my users to deep link to the content. So every time someone clicks on a link I'd like to change the URL that can be copied and pasted to another browser. Some other user could just click the link and see the same state the first one saw.

Currently I change the location with code similar to this one:

  $scope.$on('mapRegionClick', function($scope, regionCode) {
    var url = generateURL(regionCode);

    $scope.currentScope.$apply(function(){
      $location.path(url);
    });});

The URL is then picked up in my routing and the map plus data displays correctly. The downside of this is that every time I click on the map and URL changes the whole template / view is regenerated. Because generating the map is kind of heavy I'd like to trigger only a change to the data presenting controller.

Is it possible? How?

I could do some communication between controllers and achieve the my goal but then I would not be able to do deep linking.

PS: I do not want to use $location.search() and reloadOnSearch=false. my links have to be pretty :)

4
  • did you try putting the map outside of the ng-view and linking its controller to the one that is attached to the route using a shared service? Commented Jan 23, 2013 at 20:27
  • the thing is i need the map to be inside the ng-view for this particular template because other parts of the site use some other templates where map is not part of them. Commented Jan 23, 2013 at 23:03
  • It's a big shame that angular doesn't provide a clean out-of-the-box way of doing this. I love angular, but this is the reason I preferred Ember on one of my projects. Commented Oct 7, 2013 at 11:56
  • Let the controllers reload; persist the data of the controllers inside of a service. Commented Oct 19, 2013 at 19:37

2 Answers 2

9

Sounds like you don't want to use $route service.

The $route service is designed to reload the controllers so that there is no difference between navigating to a URL and refreshing the URL. We do this by doing a full reload on every URL change. This is intentional.

Sounds like your use case, should not be using $route, just $location and ng-include.

Sign up to request clarification or add additional context in comments.

Comments

0

You can use $locationChangeStart event to store the previous value in $rootScope or in a service. When you come back, just initialize all the previously stored values from the $rootScope. Check this quick demo using $rootScope.

enter image description here

var app = angular.module("myApp", ["ngRoute"]);
app.controller("tab1Ctrl", function($scope, $rootScope) {
    if ($rootScope.savedScopes) {
        for (key in $rootScope.savedScopes) {
            $scope[key] = $rootScope.savedScopes[key];
        }
    }
    $scope.$on('$locationChangeStart', function(event, next, current) {
        $rootScope.savedScopes = {
            name: $scope.name,
            age: $scope.age
        };
    });
});
app.controller("tab2Ctrl", function($scope) {
    $scope.language = "English";
});
app.config(function($routeProvider) {
    $routeProvider
        .when("/", {
            template: "<h2>Tab1 content</h2>Name: <input ng-model='name'/><br/><br/>Age: <input type='number' ng-model='age' /><h4 style='color: red'>Fill the details and click on Tab2</h4>",
            controller: "tab1Ctrl"
        })
        .when("/tab2", {
            template: "<h2>Tab2 content</h2> My language: {{language}}<h4 style='color: red'>Now go back to Tab1</h4>",
            controller: "tab2Ctrl"
        });
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular-route.js"></script>
<body ng-app="myApp">
    <a href="#/!">Tab1</a>
    <a href="#!tab2">Tab2</a>
    <div ng-view></div>
</body>
</html>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.