AngularJS different views based on Desktop or Mobile

Solution 1:

if you wanted to use the same URL but serve two different sets of HTML (say swap out large images and inpage videos for something else) I would do something like this

'use strict';

angular.module('MyApp', []).config(function ($routeProvider) {
// Magic sauce, imediate so the value is stored and we don't need to lookup every check
    var _isNotMobile = (function() {
        var check = false;
        (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
        return !check;
    })();

    // Swap out different HTML because you want to say, hide a video etc.
    $routeProvider
        .when('/', {
            templateUrl: (_isNotMobile )? 'views/MY_DESKTOP_VIEW.html':'views/m/MY_MOBILE_VIEW.html',
            controller: (_isNotMobile )?'MyHomeCtrl':'MyMobileCtrl'
          })
          .otherwise({
            redirectTo: '/'
          });
});

Solution 2:

How I would go about with this is to display one template to the user and make the template Responsive. Just because you are using AngularJS templates, I do not see a reason why you would not want to make the template responsive. I would not go for the solution that involves displaying a different template to the user based on the device browser.

That said, one way that I would do is:

  1. To have a simple script for the home / landing page of the web application that determines the browser / device. This can be found here.
  2. Next, depending on the browser / device, you redirect the user to a different route
  3. Have different routes based on the browser / device type - display a different template based on the route and thus identify if it s a mobile device or not based on the route.

The last step would be something like:

angular.module('myApp', []).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      //Display desktop version
      when('/desktop/homePage', {
        //Template for Desktop based browsers
        templateUrl: 'partials/desktop/home-page.html'
      }).
      //Display mobile version
      when('/mobile/homePage', {
        //Template for Mobile based browsers
        templateUrl: 'partials/mobile/home-page.html'
      }).
      otherwise({redirectTo: '/desktop/homePage'});
}]);

Solution 3:

Responsive design will work well for smaller apps but gets rather messy when you move to bigger applications.

I'd personally suggest detecting the user agent on page load, and redirecting him to a separate mobile app if needed. You can still use most of your code base for both apps (simply import individual modules).

If your interested in detecting the user agent using javascript I suggest this solution (simply select javascript): http://detectmobilebrowsers.com/ the most extensive solution I've found so far

Solution 4:

use boostrap. and it could be easily done.

 <!-- Display Only Screen > Big -->
 <div class="hidden-xs">
    <div ng-view class="section" ng-class="animate"></div>
    </div>
  <!-- Display Only Screen < Small -->
  <div class="visible-xs">
      <div ng-swipe-right="openSlide()">
        <div ng-view class="section" ng-class="animate"></div>
      </div>
 </div>

and in landing.html

  <div class="visible-xs" ng-include="'{{template path}}/desktop.html'" ></div>
  <div class="hidden-xs" ng-include="'{{template path}}/mobile.html'" ></div>

ANd in config

 $routeProvider
    .when(/,{
     templateUrl : "landing.html"
     controller : "landingCtrl"
    });

it works floawlessley for me. Its not of the way. maybe there could be another using pure JS. This just happened pout of the box since i am using boostrap and leverage it to my advantage.

Solution 5:

A bit late, but in something like your header, or nav controller, you could set the initial width:

angular
    .module('myApp')
    .controller('navCtrl', ['$rootScope', '$window',
        function($rootScope, $window) {
            $rootScope.is_mobile = ($window.innerWidth < 480);

And if you want checking on resize, go ahead and bind it:

angular.element($window).bind('resize', function() {
    $scope.$apply();
});

Then watch it:

$scope.$watch(function () {
    return $window.innerWidth;
}, function (innerWidth) {
    $rootScope.safeApply(function () {
        $rootScope.is_mobile = innerWidth < 480 // went with max device width
    });
});

Then in your HTML:

<div ng-if="$root.is_mobile">Show me only in mobile</div>