5

For any given route or state in an AngularJS application, I would like the option to use a mobile specific or desktop specific template depending on the user's device. I also want the user to be able to choose which version (desktop or mobile) regardless of the device they are on.

Specifically, I want a separate template because in many cases a separate template is far simpler than using responsive design.

Is there a simple way to accomplish this?

Here is what I would like to do, but I don't know how to make an 'isMobile' variable accessible to the templateUrl function using the angular-ui-router. Any help will be greatly appreciated.

angular
    .module('app.items', [])
    .config(config);

function config($stateProvider) {

    //$window service not available in config block, so how can I set this variable?
    var isMobile = $window.sessionStorage.getItem('isMobile'); 

    $stateProvider

    .state('itemsList', {
        url: '/items',
        templateUrl: function($stateParams) {

            if (isMobile) {  //How do I get this information (variable) in here?
                return 'app/items/list.mobile.html';
            }
            else {
                return 'app/items/list.desktop.html'
            }

        },
        controller: 'ItemsListController'
    });

}
Corey Quillen
  • 1,566
  • 4
  • 24
  • 52
  • `isMobile` is available inside of `templateUrl` function. Did you try to run your code? – dfsq Oct 06 '15 at 19:57
  • I know it is successfully referencing var isMobile from above, but how do I set that from a 'global' location like $window.sessionStorage? – Corey Quillen Oct 06 '15 at 20:07

2 Answers2

1

You may want to just by pass angular and use the native window.sessionStorage or if you want to let your user save a preference, window.localStorage. The $window service is essentially just a wrapper around this anyway.

Mike Feltman
  • 5,160
  • 1
  • 17
  • 38
0

You can set that with a constant (assuming you can process the constant value before the app is bootstraped).

angular.module('app.items')
    .constant('isMobile', window.sessionStorage.getItem('isMobile'));
    .config(['$injector', function($injector) {
        var $stateProvider = $injector.get('$stateProvider'),
            isMobile       = $injector.get('isMobile');
    ]});

EDIT TO ALLOW USER TO TOGGLE TEMPLATES

If you want to allow the user to make the selection, I would recommend creating a factory to get/set that value.

angular.module('app.items')
    .factory('isMobile', [function() {
        return {
            get: function() { return $window.sessionStorage.getItem('isMobile'); },
            set: function(bool) { $window.sessionStorage.setItem('isMobile', bool); }
        };
    }]);

Then in your $stateProvider

angular.module('app.items')
    .config(['$stateProvider', function($stateProvider) {
        $stateProvider
            .state('itemsList', {
                url: '/items',
                templateUrl: ['$stateParams', 'isMobile', function($stateParams, isMobile) {
                    if (isMobile.get()) { return '/mobile/template.html'; }
                    else { return 'desktop/template.html'; }
                }],
                controller: 'ItemsListController'
            });
    }]);

The update will only happen on state change using this method, but you could feasibly perform some task on isMobile.set that would force the change.

Caleb Williams
  • 1,035
  • 5
  • 12
  • How would I allow the user to select the mobile or desktop site regardless of the device they're on using this pre-bootstrap technique? – Corey Quillen Oct 06 '15 at 21:10
  • I didn't take that into account on my original answer. I've updated my answer to use a factory instead. – Caleb Williams Oct 06 '15 at 21:43
  • I guess it's just semantics, but I decided not to suggest a constant simply because the value isn't constant and would be controlled by user selection. – Mike Feltman Oct 07 '15 at 02:02
  • This is close, but the templateUrl part does not work. Refer to this answer to load the template dynamically: http://stackoverflow.com/a/25596163/6997327 – Richard Morgan Feb 27 '17 at 18:22