How do I activate otherwise on ui.router for Angular 1? - angularjs

I have a situation where a third party library adds "#checkout" at the end of the URL (it's Snipcart) but Angular cannot seem to detect it and it just goes back to the /test page (localhost:3000/test).
The reason the URL is: /test is intentional as I have html5mode enabled.
This works well in a normal static HTML project (so not Angular) but when I used ui.router with Angular 1.x, it doesn't work.
My angularApp.js file:
var mainApp = angular.module('mainApp', ['ui.router']);
mainApp.config(function($locationProvider, $stateProvider, $urlRouterProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise(function(){
console.log('otherwise activated');
});
var helloState = {
name: 'root',
url: '/',
templateUrl: '/partial/main.html',
controller: 'mainController'
}
var aboutState = {
name: 'test',
url: '/test',
views: {
'#': {
templateUrl: '/partial/yamuna.html',
controller: 'testController'
}
}
}
$stateProvider.state(helloState);
$stateProvider.state(aboutState);
});
mainApp.controller('mainController', ['$scope', '$rootScope', function($scope, $rootScope){
console.log('mainController activated');
}]);
mainApp.controller('testController', ['$scope', '$rootScope', function($scope, $rootScope){
console.log('testController activated');
}]);
So the paths below work as expected:
localhost:3000/ ##mainController activated
localhost:3000/test ##testController activated
But, Snipcart appends the path to:
localhost:3000/test#checkout - which I want to be able to go to the otherwise route and not fall back to localhost:3000/test#
Any way around this? As Angular 1 is quite old, I will have to come up with a workaround myself.
Edit
I can detect the path change with: (FYI this one below is in ngRoute as I was playing around with the various options):
mainApp.run(
['$rootScope', '$location', '$window', function($rootScope, $location, $window) {
$rootScope.$on("$routeChangeStart",
(event, current, previous, rejection) => {
console.log($window.location.href);
})
}])
But - what do I do after that? I can filter out only that specific path where #/checkout is hit but where do I redirect the site to? Not sure if this is even worth an edit but I thought I will mention it for completeness.
My ONLY option it seems is to upgrade to Angular 8 or higher but as I am so close to the deadline, I will like to explore all the options with Angular 1.x first.
Thanks

Related

$stateParams is empty object

i saw a lot of similar questions at SO, but those solutions not worked for me :(
About my site and app:
backend is wordpress with json api, angular app is on the mysite.lc/catalog/ page.
my controller:
var catalogControllers = angular.module('catalogControllers', []);
catalogControllers.controller('catalogCtrl', ['$scope', '$state', '$stateParams',
function ($scope, $state, $stateParams) {
$log.debug(angular.toJson($stateParams, true));
$http.get(url).success(function(data) {
console.log('data is loaded');
});
}
]);
my routing setup:
var catalogApp = angular.module('catalogApp', ['ui.router', 'ngResource', 'ngSanitize', 'catalogControllers']);
catalogApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '?producttype&colors&models',
controller: 'catalogCtrl',
onEnter: function() {
console.log('route entered');
}
});
$urlRouterProvider.otherwise("/");
}]);
So when i go to url like http://mysite.lc/catalog/#/?producttype=4&colors=5,7,9&models=17 console shows
{} from catalogCtrl, then
data is loaded from catalogCtrl $http.get, and only after that
route entered
If i do log it that way (at router config) controller: function($stateParams) { console.log($stateParams); } it doesn't output anything.
I would suggest resolving the $stateParams on its corresponding state on the .config section. Also,if it is your intention, you need to make your url name part of the url property and not just the stateParameters because ui-router doesn't automatically assign 'home' just because you declared it to be the home state. You can also make the parameters optional by declaring the 'params' property and setting everything to null.
var catalogApp = angular.module('catalogApp', ['ui.router','ngResource', 'ngSanitize', 'catalogControllers']);
catalogApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
params: {
productType: null,
colors: null,
models: null
}
url: '/home?productType&colors&models',
controller: 'catalogCtrl',
resolve: {
parameters: function($stateParams){
return $stateParams;
}
}
});
$urlRouterProvider.otherwise("/");
}]);
and to view it in the console, I would suggest using $log to preserve the sequence of it (I had this problem before using console.log) and angular.toJson to display the data;
var catalogControllers = angular.module('catalogControllers', []);
catalogControllers.controller('catalogCtrl', ['$scope', 'parameters', '$log'
function ($scope, parameters, $log) {
$log.debug(angular.toJson(parameters, true));
//the 'true' arguments makes the json 'prettyfied'
}
]);
let me know how it goes because it's a bit unorthodox for me to create the app which doesn't start from the root page.
I've found what was the problem, and it's small and easy (as usually :) ).
Actually everything worked fine, but i had some unmentioned $http.get calls in code above, and my logging was before any data has been loaded, so firstly i logged my $stateParams and only after that (after data has been loaded) my "home" state has been achieved.
So solution is to put work with $stateParams into $http.get(..).success() function.
So now my controller looks like
var catalogControllers = angular.module('catalogControllers', []);
catalogControllers.controller('catalogCtrl', ['$scope', '$state', '$stateParams',
function ($scope, $state, $stateParams) {
$http.get(url).success(function(data) {
console.log('data is loaded');
$log.debug(angular.toJson($stateParams, true));
});
}
]);
router:
var catalogApp = angular.module('catalogApp', ['ui.router', 'ngResource', 'ngSanitize', 'catalogControllers']);
catalogApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '?producttype&colors&models',
controller: 'catalogCtrl',
onEnter: function() {
console.log('route entered');
}
});
$urlRouterProvider.otherwise("/");
}]);
URL like http://mysite.lc/catalog/#/?producttype=4&colors=5,7,9&models=17 now outputs in console this:
data is loaded from $http.get in controller
route entered from router
{ "producttype": "4", "colors": "5,7,9", "models": "17" } from $stateParams in controller
Please add your comment, because i'm really newbie in angular and will appreciate any opinions on that.

ngRoute not directing to anything

So I'm trying to learn how to use Angulars routing, following tutorials online, and I can't seem to figure out where I'm going wrong. I have the following code:
var app = angular.module('gamersplane', ['controllers', 'ngCookies', 'ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/pms/:box?', {
controller: 'pmList'
}).when('/pms', {
controller: 'pmList'
}).otherwise({
controller: 'pmList'
});
}])
var controllers = angular.module('controllers', []);
controllers.controller('pmList', function ($scope, $cookies, $http, $routeParams) {
console.log($routeParams);
});
However, no matter what I do, the controller doesn't get hit. I have otherwise in the router, so isn't that where it should hit if all else fails?
Yes it will hit otherwise but you can only define the redirect path into it and that redirect path will tell the url and the controller to set for the $route.current :-
redirectTo: '/pms'
Doc
You need to add a template to each route:
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/pms/:box?', {
controller: 'pmList',
template: 'test.html'
}).when('/pms', {
controller: 'pmList',
template: 'test.html'
}).otherwise({
controller: 'pmList',
template: 'test.html'
});
}])
squiroids suggestion regarding otherwise was correct, you won't see a change in your test application though.
Routing is meant to be used to navigate between regions of your application. You could have an app with two routes: pms which shows a list of PMs and pms/:box zu view a particular PM Box. The main task for ngRoute is to replace a placeholder in your application (ng-view) with a given template. Without using a template on the individual routes, your $routeProvider will not navigate as expected.
Given you have two views for the regions (pmBox.html and pmList.html), you could configure your $routeProvider zu setup routing like this: https://gist.github.com/kpko/bd0231ccefbaf8c415c7

Angular JS remove hash from URL not working

I am trying to get rid of the url looking like http://example.com/#/album/0 and have it look more like http://example.com/album/0.
I have the following code
(function() {
var app = angular.module('chp', ['ngRoute', 'projectControllers']);
app.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'partials/directory.html',
controller: 'ProjectsCtrl'
}).
when('/album/:id', {
templateUrl: 'partials/album.html',
controller: 'ProjectDetailCtrl'
}).
otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
}]);
var projectControllers = angular.module('projectControllers', []);
projectControllers.controller('ProjectsCtrl', ['$scope', '$http',
function ($scope, $http) {
$scope.projects = albums;
$scope.filters = { };
}]);
projectControllers.controller('ProjectDetailCtrl', ['$scope', '$routeParams', '$sce',
function($scope, $routeParams, $sce) {
$scope.project = albums[$routeParams.id];
})();
but this is causing my app the break entirely once I add in $locationProvider in the three places shown. Any idea as to why this is not working for me? Also I am including angular-route.js just after jquery and angular.js so that cant be the problem
At a glance it looks all right to me, but you must make sure your server is set up to serve http://example.com/index.html for any route, otherwise it will try to load http://example.com/album/0/index.html before bootstrapping your angular application. What do you see when you enable html5? 404 not found? Console error?
You might also need to add
<base href="/" /> inside <head></head> in your index.html file

AngularJS location redirect in AppCtrl, without load the current controller

I'm pretty new to AngularJS,- in my AngularJS app I have a check in my AppCtrl controller if we have to redirect or not.
.controller('AppCtrl', function($scope, $location) {
if(window.localStorage.getItem("lastStation")) {
$location.path('/app/player/'+window.localStorage.getItem("lastStation"));
}
....
.controller('PlayerCtrl', function($scope, $stateParams) {
alert($stateParams); // This one is alerted TWICE if the $location.path is called in the AppCtrl controller
Hope someone can help with that! ;)
You must have configured routing for your application, like:
yourApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/app/player/:lastLocation', {
templateUrl: 'path_to_your_view',
controller: 'PlayerCtrl'
}).
.....
}]);
Now I got it ;)
.run(function($rootScope, $location) {
if(window.localStorage.getItem("lastStation")) {
$location.path('/app/player/'+window.localStorage.getItem("lastStation"));
}
});
I had to make the check in a .run method.

Build URLs based on routes

Is there a way to build an URL based on the defined Angular routes? Something like Symfony does (http://symfony.com/doc/current/book/routing.html#generating-urls).
Here is an example of how it would be used:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/document/:documentId', {
name: 'document',
templateUrl: 'partials/document.html',
controller: 'documentController'
});
}]);
Then in templates we could use something like:
View document
That would be compiled into:
View document
I have user $stateParams (from angular-ui-router) for this.
.controller('MainCtrl', function ($scope, $stateParams) {
$scope.link = $stateParams.documentId;
});
UI Router wiki on Github

Resources