3

I'm using ngRoute in angularjs to delegate different html templates, eg:

phonecatApp.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/phones', {
        templateUrl: 'partials/phone-list.html',
        controller: 'PhoneListCtrl'
      }).
      when('/cars', {
        templateUrl: 'partials/car-detail.html',
        controller: 'CarDetailCtrl'
      });

    //many more routes
  }]);

Problem: I want to have a common url, like localhost/my-app?myparam=Nokia.

I want to compare the myparam to a mapping table. If the param name is a phone company, I want to delegate to /phones. If it's a car company, I want to delegate to /cars, etc. You get the idea.

Also I have to rewrite the url as follows: localhost/myapp/phones?myparam=Nokia. Thereby the ngRoute would automatically catch the correct template and controller.

Question: how can I intercept the initial loading, and redirect based on the url param?

Sidenote: I cannot rewrite the routeProvider config eg by using a different plugin like angular-ui-router.

3 Answers 3

3

It sounds like you might want to take a step back and reconsider why you're trying to tackle it this way but given your constraints, your best bet may be to have a service that returns the correct URL and call it from the controller:

phonecatApp.controller("trafficCtrl", function ($routeParams,trafficService,$location) {
    if ($routeParams.myparam) {
        var destination = trafficService.getDestination($routeParams.myparam);
        $location.path(destination);
    }
})
.service("trafficService", function () {
    this.getDestination = function (paramValue) {
        switch(paramValue) {
            case "Nokia":
                return "/phones";
            case "Ford":
                return "some/car/url";
            // etc...
        }
    }
});

Also, you have to add the following (generic) route to the provider:

$routeProvider.when("/", {
      template: '',
      controller: 'trafficController'
});
Sign up to request clarification or add additional context in comments.

8 Comments

But would this approach automatically link templates to controllers? That's what I like most about ngroute, explicit linking them together and invoke them just by the url path.
@membersound - yes it would. Let's say that myparam is "Nokia". It would redirect the user to partials/phone-list.html at which time $routeProvider would realize it and know to use the corresponding template and controller
So I'd have to keep my .config of ngRoute, and additionally use your servicecontroller approach to call these routes? If yes, how can I ensure that your controller intercepts before the ngRoutes are evaluated?
And moreover: shouldn't I return case "Nokia": return "/phones"; in the switch statements?
Correct, keep your .config and then call the service. You shouldn't need to worry about ngRoute doing any unintended evaluating because you'll direct all traffic the the trafficCtrl controller first, which will then forward them to the correct path, at which point ngRoute kicks in.
|
1

I don't know if this is right solution.. But you can create a new route /myapp .. Write a controller and redirect using $location service .. After finding the query para value using $location.query() and redirect it accordingly

4 Comments

Hm, is that advisable? Especially from performance point of view?
I am a newbie .. so my knowledge is limited but I don' t think performance will impact that much but if you are redirecting for a particular route.
you can also write it inangular.run but i wont recommend it as run will run before controller for every view loaded. so if u open other url's which don't need redirection the code will run but if every url user accesses need to be redirected then u can consider run as it will load before any controller or directives. you can keep the redirection code in different module and import it to tour original one and redirect it in angular run so that the url will be intercepted before loading of other elements. (my guess is that performance will not be impacted.. but you need to check about it)
I only need the redirect to be run once on first access. During navigation on my page, it should not run again.
0

If we make it a REST call like /my-app/Nokia or my-app/Samsung instead of Query params, I think we can dynamically route it in the config itself.

phonecatApp.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/my-app/:myparam', {
        templateUrl: function(params){
         return TemplateMappingFunction(params.myparam) +'.html'
    },
        controller: function(params){
         return ControllerMappingFunction(params.myparam)
    }
      })

    //many more routes
  }]);

For example,

  • if the URL is /my-app/Nokia, TemplateMappingFunction(Nokia) will return partials/phone-list.html',
  • if the URL is /my-app/Nokia, TemplateMappingFunction(Nokia) will return partials/phone-list.html',
  • if the URL is /my-app/BMW, TemplateMappingFunction(BMW) will return partials/car-details.html',

Query Param approach

 phonecatApp.config(['$routeProvider',
          function($routeProvider) {
           /* Function to retrieve Query parameters*/
           function getParameterByName(name) {
                name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
                var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
                    results = regex.exec(location.search);
                return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
            }

            $routeProvider.
              when('/my-app', {
                templateUrl: TemplateMappingFunction(getParameterByName('myparam'))
            },
                controller: ControllerMappingFunction(getParameterByName('myparam'))
            }
              })

            //many more routes
          }]);

So, if the URL is localhost/my-app?myparam=Nokia, then TemplateMappingFunction('Nokia') will return 'partials/phone-list.html'

2 Comments

Great approach, but unfortunately I have no impact on the url, so I have to stick to evaluate by query param(s).
In that case the above code (Query Param approach) should do the job.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.