This question may have been asked before. But here goes:
My website is http://thecheeknee.com.
The site basic structure is as follows:
`index.html
js|-app.js
js|ctrls|pageLoad.js -common controller for all pages
js|srvc|Datamap.js
templates/-about.html, etc`
The HTML basic view is as shown below:
<section ui-view></section>
The UI router angular code is as follows:
angular
.module('app',[
'ui.router',
'ngStorage'
])
.config(['$urlRouterProvider','$stateProvider',function($urlRouterProvider, $stateProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home',{
url:'/',
templateUrl:'templates/home.html',
controller:'pageLoad'
})
The controller is very basic.
angular
.module('app')
.controller('pageLoad',[ '$scope', 'Datamap', function($scope, Datamap){
$scope.title = "thecheeknee";
//$scope.$storage = $localStorage;
//$scope.$storage.counter = $scope.$storage.counter+1 || 0;
Datamap.getData().then(function(response){
$scope.datamap = response.data;
});
The Data map service is as follows:
angular.module('app')
.factory('Datamap', function($http) {
//debugger;
return{
getData: function(){
return $http.get('data/data.json',{ cache: true});
}
}
});
The site works perfectly on the desktop across multiple browsers. But Chrome App on Android seems to load a blank page.
(I had designed the site to be responsive and had tested the UI thoroughly using Chrome's browser tool)
On observing, I noticed that the browser adds a #!/ and loads the view into the page. On the mobile browser however, it seems to be stopping at the site name itself (#!/ is not being added). So I assume the UI router is unable to load the route into the page.
I am relatively new to Angular, so is there anything minor I am missing out here?
Full source code at: https://github.com/thecheeknee/sitebase.git
Related
I have several html pages, each with an angular app isolated without routing (the app is not a Single Page Application)
//new anguar app in each page
var app = angular.module('app', ['ui.bootstrap', …
My token is stored into the localstorage so to secure the application i've added in each pages this block of code:
app.run(function ($window, $localStorage) {
…
if (!$localStorage.currentUser)
$window.location.href = 'Login.html';
});
This approch seems to work, but does exist a better way considering that no routing is used in this application?
I'm following a tutorial on how to set up authentication with nodejs and passport. (http://scotch.io/tutorials/javascript/easy-node-authentication-setup-and-local)
The tutorial has me rendering templates with ejs and passing in flash data.
Instead of this, I'd like to use angularjs. The part I'm having trouble with is getting the flash data. I know how to use templates and send variables, but what in angular replaces the "req.flash('signupMessage')" in the below code?
This is the code the tutorial shows:
app.get('/signup', function(req, res) {
// render the page and pass in any flash data if it exists
res.render('signup.ejs', { message: req.flash('signupMessage') });
});
This is the code where I set up my route
// public/js/appRoutes.js
angular.module('appRoutes', []).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
// show signup form
.when('/signup', {
templateUrl: 'views/signup.html',
controller: 'SignupController'
});
$locationProvider.html5Mode(true);
}]);
Here is the controller:
// public/js/controllers/SetupCtrl.js
angular.module('SignupCtrl', []).controller('SignupController', function($scope) {
$scope.tagline = 'TEST';
});
A similar question was answered here: What is the proper way to log in users using Angular & Express?
TLDR: the answer posted was to the following link, where the author describes that you need to keep all the passport stuff on the server side, and then allow the client side (angular stuff) to request information about the session.
http://vickev.com/#!/article/authentication-in-single-page-applications-node-js-passportjs-angularjs
I current working Web Application with Angular JS.
I using a Angular route to implement a Single page Application.
This is my implemented code to route.
config(function($routeProvider){
$routeProvider
.when('/init',{templateUrl:'/member/join?m=init'})
.when('/begin',{templateUrl:'/member/join?m=begin'})
.when('/end',{templateUrl:'/member/join?m=end'})
.otherwise({redirectTo:'/'});
}).
I was stuck with a problem.
AngularJS Router is update after page loading.
<body>
<ng-view>
</ng-view>
</body>
But, I can't update direct way without Angular Router.
I wonder how to update without angular router.
Example.
ontroller('registerController', function($scope, $http, baseUrl) {
$scope.register = function() {
var reqPromise = $http.post(baseUrl+'member/join',$scope.user);
reqPromise.success(function(data, status, headers, config) {
/// <-- i want to update <ng-view> without router. Just, direct update <ng-view>!
});
help me.
Express.js routing of /question/ask
app.get('/question/ask', function (req, res){
console.log('index.js');
console.log('came to question/:id');
res.render('app');
});
The corresponding angularjs routing is:-
when('/ask', {
templateUrl: 'partials/askQuestion',
controller: 'xController'
}).
whereas it should be:-
when('/question/ask', {
templateUrl: 'partials/askQuestion',
controller: 'xController'
}).
I'm working in $locationProvider.html5Mode(true); mode.
Is there anyway i can get the later angularjs routing working. I'm using angularjs 1.1.5 version.
Edit:-
app.get('/*', function (req, res){
console.log('index.js');
console.log('came to question/:id');
res.render('app');
});
has the same problem, the angular route only routes the last /ask for /question/ask.
The issue for me is that I can only do 1 of the following :-
www.example.com/question/:qId
www.example.com/discussion/:aId
because the application will catch only 1 when('/:id', { as it does not include the previous /question/ or /discussion/
Well, if you have the same routes on Express and Angular, if the user types the url directly in the browser you will hit the Express route, but if the user is navigating within the application, then he will hit the Angular route.
Is this what you want ?
What some do is to have a different set of routes on the server for the REST API, and a catch all route to serve the application no matter what the user type as a URL, bringing the user to the home page when a server route is hit. Within the application of course navigation is handled by Angular routes. The problem is that you get no deep linking.
Some other apps have the same routes on both the server and the client, this way they can serve some contents no matter what.
Some will write involved route rewriting to make sure that you both get the application bootstrapping code AND the required URL, thus allowing deep linking.
Cheers
using angular version 1.2.0-rc.3 cures the problem.
change:
var myApp = angular.module('myApp', []);
to
var myApp = angular.module('myApp', ['ngRoute']);
And include:-
script(type='text/javascript', src='js/angular-route.js')
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 ?
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: '/'
});
});
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'});
}]);
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
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.
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>
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