I would like to use AngularJS
for a single page webapp.
I am concerned if there is an elegant way to "send" different templates based on whether the client is a mobile or desktop.
Is there any way to do it ? Is it recommended that web server "understand" what the browser is and send the view accordingly so the browser always asks for template.html OR you write javascript so the browser will tell webserver to get the mobile/template.html ?

- 1,383
- 8
- 26
- 38
-
This decision should be done on server side based on type of browser requesting the resource.You should opt some typ of DDR to find the browser capabilities – Ajay Beniwal Apr 30 '13 at 10:17
6 Answers
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: '/'
});
});

- 817
- 1
- 6
- 12
-
2Interesting implementation. You're stuck with the template at page load time. Once angular has "bootstrapped" itself, that's it. – Dave Jul 25 '14 at 15:11
-
You could probably do something clever to check changes in size and have it re-"bootstrap" itself in a sense, though it seems like it would be awkward. Apart from those odd cases though, this seems like a very viable option to keep consistency in the url. – Kinetic Stack Sep 25 '17 at 13:19
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:
- To have a simple script for the home / landing page of the web application that determines the browser / device. This can be found here.
- Next, depending on the browser / device, you redirect the user to a different route
- 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'});
}]);

- 1
- 1

- 10,989
- 15
- 69
- 104
-
I am going with responsive design as its the need for today's web apps – lostpacket Apr 30 '13 at 15:57
-
16Just adding 2 cents. Yeah adding responsiveness is very easy to do with tools like Bootstrap 3 but in some cases the developer needs to display two different pages depending on device because 1) Designers talk about responsive-design but do not understand it and will deliver designs which incorporate elements from multiple pages/views. At this point you need a solution which allows you to provide a controller/view which is mobile specific. – creamcheese Feb 22 '14 at 16:33
-
Almost 4 years later and yes I agree with @DominicWatson. The responsive thing was nice and all but the reality is there are just different design patterns completely when working with mobile that responsive designs don't cover. It's a nice cheap way to write once and may work in come cases but will never give a more true mobile design feel. – user441521 Oct 31 '18 at 18:17
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

- 1,385
- 2
- 14
- 26
-
In my app, people are going to share the links. So if someone sends a desktop url by email to other person and the other person has a mobile device, can the url be redirected to the mobile version of that url ? – lostpacket Apr 30 '13 at 15:44
-
For e.g. : Link in the email : `http://server/unit/20` Link should be redirected to : `http://server/mobile/unit/20` – lostpacket Apr 30 '13 at 15:47
-
The redirection script in my original comment always redirects you to the same url, but you can modify it to catch the current user url and simple add mobile to the beginning of the path (user location.pathname to catch the current page) – Guy Nesher May 01 '13 at 13:39
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.

- 545
- 2
- 7
- 24
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>

- 12,432
- 33
- 128
- 268
BOOSTRAP + ANGULARJS solution to this problem:
You can check out the angular-match-media
library. It is extremely small in size but very helpful and elegant.
https://github.com/jacopotarantino/angular-match-media
**Watch out: This is installed with bower install angular-media-queries
; however, the path to the js file is /path/to/library/angular-media-queries/match-media

- 21,375
- 7
- 100
- 81