6

I've been working on a large Angular app for almost a year now and I'm stuck trying to do what I expected to be trivial.

Here are two routes I have with params (shortened for brevity):

/a/:id
/a/:id/b

Let's say the user is at /a/1 and the query string is modified, for example:

/#/a/1?foo=123&bar=456

I want to have a link on the page that directs the user to the second route /a/1/b while maintaining the query string, so the end result is a redirection to:

/#/a/1/b?foo=123&bar=456

I am using Angular 1.2 and the new ngRoute module.

What is the best way to achieve this behavior?


Edit: I should mention I have a working solution right now that seems terrible to me. The link is bound to an ng-click handler which is essentially the following:

$scope.navigateToBClick = function() {
  var path = $location.path() + '/b',
    search = $location.search();
  $location.url(path + '?' + $.param(search));
};
3
  • have you figured out another solution yet? This does seems terrible to me. Commented Jan 15, 2014 at 16:21
  • you could just call $location.path($location.path()+ '/b'); instead of what you are doing. The search string will be appended when changing routes using path. Explain what you find terrible please. Commented Feb 13, 2014 at 1:33
  • I have the exact opposite problem. My query string always persists, and I don't want it to do so. I'm using the default $locationProvider.html5Mode = false. I imagine if we resolve one problem, the other will be trivial. Also, my links are in <a> tags. I'm wondering if this is part of the issue. Commented Oct 28, 2014 at 19:04

6 Answers 6

5
+50

I'm not sure if you would consider this a better solution than what you've got, but it is a solution.

In your initialization code, add the following:

app.run(["$rootScope", function ($rootScope) {
    $rootScope.$on("$routeChangeSuccess", function (e, current) {
        $rootScope.query = $.param(current.params);
    });
}]);

Then, in your HTML, make your links as follows:

<a ng-href="#/a/{{id}}/b?{{query}}">Navigate to B</a>
Sign up to request clarification or add additional context in comments.

1 Comment

Consider using ng-href instead of href when you have {{}} in your url. See docs.angularjs.org/api/ng/directive/ngHref
1

If i understand correctly the question then we can solve it with $locationChangeStart $rootScope event. This is done in run phase. Basic idea is : on every location change we will check if we had query string in url (searching for '?' in the url, if there is query string , then we add it to the new url.

    angular.module('your_module').run(function ($rootScope) {
      $rootScope.$on('$locationChangeStart', function (event, newUrl, oldUrl) {

      // If we have queryString on currentURL , then we will add it to the next url
        if(oldUrl.indexOf('?') >= 0) {
         // this can be optimized if we want to check first for queryString in the new url,
         // then append only new params, but that's additional feature.
        newUrl += '?' + oldUrl.split('?')[1];
      }
   });

In HTML we just call $location.path('a/1/b') , url params (query strings) will be added automatically.

Comments

0

if route is /#/a/1?foo=123&bar=456 then redirect to /#/a/1/b?foo=123&bar=456

I have worked on /#a?foo=bar to /#b?foo=bar, it can be easily tweaked to /#a/b?foo=bar and used angular-route-segment library.

Run the plunker at http://run.plnkr.co/HvSyw4aMUiy1mwC3/#/firstRoute?foo=bar

and see the code here

http://plnkr.co/edit/ylFM8BHRXpqpMV7QVEcJ

Please let me know if it works.

Comments

0

Another solution I've found so far is to trace all $location.search() changes and store $window.location.search in a scope variable after each search change.

Then just add this scope variable to all anchors in a template:

<a ng-href="/projects/{{ projectId }}{{ queryString }}">
    Title
</a>

In this case both routes reads scope variables from routeParams query string and uses $scope.$watch on those variables to reflect changes in $location.search and thus in anchors href attributes accordingly.

Comments

0

//Controller

$scope.menu = {path:"admin", name: "Administration"};
var queryString = $location.$$url.split("?")[1];
if (queryString) {
    $scope.queryString = "?" + queryString;
}

//View

<a ng-href="#/{{menu.path}}{{queryString}}">{{menu.name}}</a>

Comments

0

Here is the solution I used that caused persistent query string propagation (that I didn't want).

el.find('li').has('ul').on('click', 'a', function (e) {
    // handle clicks manually
    e.stopPropagation();
    // if the anchor tag has a specific class
    if (el.hasClass('link')) {
        var path = el.attr('href').replace('#', '');
        scope.$apply(function () {
            // changing the path changes only the path
            // the query string is left intact
            $location.path(path);
        });
    }
});

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.