Search code examples
angularjsangularjs-routing

Multiple query string parameters in angularjs


I'm struggling with passing and reading multiple query string parameters in a route.

$routeProvider.when("/joboffers:keywords:location", {
    controller: "jobOffersController",
    templateUrl: "/App/Views/JobOffer/All.html"
});

This is the search page:

$scope.searchJobOffer = function () {
    var vm = $scope.jobOfferSearchViewModel;
    var path = "/joboffers?keywords=" +( vm.keywords || "") + "&location=" + (vm.location || "");
    $location.path(path);
}

And this is the JobOffersController:

'use strict';
app.controller('jobOffersController', ['$scope', '$routeParams', 'jobOfferService', function ($scope, $routeParams, jobOfferService) {
    $scope.jobOffers = [];

    function init() {
        var keywords = $routeParams.keywords;
        var location = $routeParams.location;
    }

    init();
}]);

Reading the $routeParams is not working at all. If I pass "developer" as a keyword and "New York" as location, the $routeParam object looks like this:

{keywords: "?keywords=developer&location=New Yor", location: "k"}

Can somebody tell me what I'm doing wrong? Thanks in advance.

P.S. Is it possible that this is because of a wrongly configured route? When I navigate via the searchJobOffer function, it encodes the URL to this: http://localhost:49380/#/joboffers%3Fkeywords=developer&location=london and if I try to use this url http://localhost:49380/#/joboffers?keywords=developer&location=london, the routing system drops me to the default route (#/home)


Solution

  • $routeProvider does not match on query strings, only routes. Also, you're setting a full url to $location.path() and $location.path() only takes the path piece of the url. To set the entire URL including query string you need to use $location.url().

    Here are a few options:

    1. Use pretty URLs instead

    $routeProvider.when("/joboffers/:location/:keywords", {
      controller: "jobOffersController",
      templateUrl: "/App/Views/JobOffer/All.html"
    });
    
    $scope.searchJobOffer = function () {
      var vm = $scope.jobOfferSearchViewModel;
      var path = "/joboffers/" + (vm.location || "") + "/" + ( vm.keywords || "");
      $location.path(path);
    };
    
    app.controller('jobOffersController', ['$scope', '$routeParams', 'jobOfferService', function ($scope, $routeParams, jobOfferService) {
      $scope.jobOffers = [];
    
      function init() {
        var keywords = $routeParams.keywords;
        var location = $routeParams.location;
      }
    
      init();
    }]);
    

    2. Only match on the job offers path and pull the params from $location.search()

    (note the use of $location.url() instead of $location.path())

    $routeProvider.when("/joboffers", {
      controller: "jobOffersController",
      templateUrl: "/App/Views/JobOffer/All.html"
    });
    
    $scope.searchJobOffer = function () {
      var vm = $scope.jobOfferSearchViewModel;
      var url = "/joboffers?keywords=" +( vm.keywords || "") + "&location=" + (vm.location || "");
      $location.url(url);
    };
    
    app.controller('jobOffersController', ['$scope', '$location', 'jobOfferService', function ($scope, $location, jobOfferService) {
      $scope.jobOffers = [];
    
      function init() {
        var search = $location.search();
        var keywords = search.keywords;
        var location = search.location;
      }
    
      init();
    }]);
    

    3. If you need to match the route AND the query string, try something more robust like angular-ui-router

    $stateProvider.state("JobOffers", {
      url: '/joboffers?keywords&location',
      controller: "jobOffersController",
      templateUrl: "/App/Views/JobOffer/All.html"
    });
    
    $scope.searchJobOffer = function () {
      var vm = $scope.jobOfferSearchViewModel;
      var url = "/joboffers?keywords=" +( vm.keywords || "") + "&location=" + (vm.location || "");
      $location.url(url);
    };
    
    app.controller('jobOffersController', ['$scope', '$stateParams', 'jobOfferService', function ($scope, $stateParams, jobOfferService) {
      $scope.jobOffers = [];
    
      function init() {
        var keywords = $stateParams.keywords;
        var location = $stateParams.location;
      }
    
      init();
    }]);