Search code examples
angularjshttp-redirectroute-provider

Angular RouteProvider redirect to another html file


I have to build an app for an existing website, but unfortunately the website (outside of my control) detects the user device and redirects to a mobile version.

I am trying to reuse the same js file but different html files.

So I have:

  1. index.html for desktop
  2. mobile.html for mobile

both call init.js where I want to handle my logic, my problem is that for some reason the routing is not working as I expected and I cannot figure out why.

Desktop:

  1. I go to example.com
  2. get redirect to example.com/#/steps/age/0
  3. Refresh the page and it stays in example.com/#/steps/age/0

This works as expected

Mobile:

  1. I go to example.com/mobile.html
  2. get redirect to example.com/mobile.html#/steps/age/0
  3. Refresh the page and instead of staying in the same url, it goes to example.com/steps/age/0#/steps/age/0

This does not work as expected (expected to stay in the same url once refreshing as in the step number 2)

Code below:

angular
.module('profileToolApp', ["ngRoute", "ngResource", "ngSanitize"])
.config(function($routeProvider, $locationProvider){
    $routeProvider
    .when('/steps/:steps*', {
        templateUrl : 'profile-app.html',
        controller : 'example'
    })
    .otherwise({
        redirectTo: '/steps/age/0'
    });
})
.controller('example', function($scope, $routeParams, $resource, $location){
    console.log("example controller");
});

Can anyone please advise? Thanks.


Solution

  • Angular is examining the entire path to see where it should route to. So when you have example.com/mobile.html#/steps/age/0 There is no matching route, so it substitutes the route for you, in place of mobile.html so you get /steps/age/0#/steps/age/0 from your otherwise. The fundamental problem is that angular has no sense of what mobile.html means, and takes it as a parameter.

    One solution is to use routes to separate your pages.

    $routeProvider
        .when('/', {
            templateUrl : 'desktop.html', //was 'index.html pre edit
            controller : 'example'
        })
        .when('/mobile/', {
            templateUrl : 'mobile.html',
            controller : 'example'
        })
        .when('/steps/:steps*', {
            templateUrl : 'profile-app.html',
            controller : 'example'
        })
        .when('/mobile/steps/:steps*', {
            templateUrl : 'mobile-profile-app.html',
            controller : 'example'
        })
        .otherwise({
            redirectTo: '/'
        });
    })
    

    Controllers may vary as needed.

    Alternatives to this are to have mobile.html use its own angular App and routing, which may be beneficial since you won't run into desktop directives leaking into mobile. You can inject all of your directives and controllers into it, but still have a nice separation of index and mobile. You can take that a step further and have a redirect to m.example.com, but that's a different topic.

    EDIT I made a mistake. Having templateUrl be index.html is a bit wrong. index.html should contain your ng-app and your ng-view directives, possibly a controller. Any common html should reside there. desktop.html and mobile.html should contain the specific HTML for those platforms.

    As an afterthought, Within those you could have a directive called profile that does all of your profile work, and with a bit of ng-switch you can have that appear if steps is defined in the scope, and use:

    $routeProvider
    .when('/steps?/:steps?', {
        templateUrl : 'desktop.html', //was 'index.html pre edit
        controller : 'example'
    })
    .when('/mobile/steps?/:steps?', {
        templateUrl : 'mobile.html',
        controller : 'example'
    })
    

    But now I'm rambling, I'm not 100% sure that will work tbh. END EDIT