Not able to change the location path - angularjs

Redirecting is not functional in the below code. My console.log() works fine, but the URL doesn't change. Needless to say, I'm confused as to why. I've changed the URL like this is another section of my application and it works great.
angular.module('workstation.process.approval', [
/* Dependencies */
'workstation.services'
]).
config(['$routeProvider', function($routeProvider) {
/* URL mappings */
$routeProvider.
when('/approval', {templateUrl: 'partials/loading.htm', controller: 'ApprovalCtrl'}).
when('/approval/dashboard', {templateUrl: 'partials/approval/dashboard.htm', controller: 'ApprovalCtrl'})
}]).
controller('ApprovalCtrl', ['$scope', '$cookieStore', 'WorkflowProcessService', 'socketUrl', '$location', function ($scope, $cookieStore, WorkflowProcessService, socketUrl, $location) {
var socket = portal.open(socketUrl+'/socket/workstation/approval');
socket.on({
open: function () {
this.send('getDashboard', {
workstationUuid: $cookieStore.get('workstationUuid')
}, function(r) {
$scope.dashboard = r;
console.log('swap-path', r);
$location.path('/approval/dashboard'); //NOT WORKING
});
},
close: function (reason) {
console.log(reason);
}
});
}]);

Try adding $scope.$apply() after you change the path. The socket on callback is called outside Angular, so you may need to tell Angular to run a digest cycle to notice the change. – Mark Rajcok May 14 at 21:18
it works for me thanks

I think, window.location() would suit your needs.
Just add
$window as a dependency
regards

Related

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

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

Controller Undefined after Form Submit: Argument 'RegistrationController' is not a function, got undefined

I wrote some custom routing in my app configuration file to handle routing of all my html templates and controllers instead of having to specifically define the route for every single html and controller. I have a Registration.html and RegistrationController.js under my Modules/Account/ directory. My app can find the controller the first time I go to it and I can fill out the page and submit the form on the page. After I submit successfully, I get redirected to a success page. When I try to go back to the same registration html/controller the 2nd time, it can find my html template, but it can not find my controller anymore and i get the error "Argument 'RegistrationController' is not a function, got undefined". Can anyone tell me why and how to fix this?
Please note this error only happens after a form submit. If I leave the page and go back to it without doing a form submit, everything works fine.
App Config
define(['angularAMD', 'angular-route', 'ui-bootstrap', 'ui-grid'], function (angularAMD) {
var app = angular.module("MyApp", ['ngRoute', 'ui.bootstrap', 'ui.grid']);
app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider
.when("/", angularAMD.route({
templateUrl: function (rp) { return 'Modules/Account/login.html'; },
controllerUrl: 'Modules/Account/LoginController'
}))
.when("/:module/:page", angularAMD.route({
templateUrl: function (rp) { return 'Modules/' + rp.module + '/' + rp.page + '.html'; },
resolve: {
load: ['$q', '$rootScope', '$location', function ($q, $rootScope, $location) {
var path = $location.path();
var parsePath = path.split('/');
var parentPath = parsePath[1];
var controllerName = parsePath[2];
var loadController = "Modules/" + parentPath + "/" + controllerName + "Controller";
debugger;
var deferred = $q.defer();
require([loadController], function () {
$rootScope.$apply(function () {
deferred.resolve();
});
});
return deferred.promise;
}]
}
}))
.otherwise({ redirectTo: '/' });
}]);
loadDirectives(app);
angularAMD.bootstrap(app);
return app;
});
RegistrationController
define(['app-config','accountService'], function (app) {
app.register.controller('RegistrationController', ['$scope', '$rootScope', '$location', '$uibModal', 'accountService',
function ($scope, $rootScope, $location, $uibModal, accountService) {
$rootScope.applicationModule = "Account";
$scope.registerUserSuccess = function (response, status) {
debugger;
$location.path("/Account/RegistrationSuccess");
}
$scope.registerUserFailure = function (response, status) {
if (!response.ValidationErrors) {
$scope.ErrorList = [];
$scope.ErrorList.push("An error occurred. Please contact the system's administrator");
}
else {
$scope.ErrorList = response.ValidationErrors;
}
}
$scope.onSubmitClick = function (isValid) {
if (isValid) {
accountService.registerUser($scope.regModel, $scope.registerUserSuccess, $scope.registerUserFailure);
}
}
$scope.onCancelClick = function () {
$location.path("/Login");
}
}
]);
});
I haven't honed in on the answer yet, but I've noticed some refactoring that you should do that might get you closer to figuring out your problem ...
Stop using controllers. Use components, which were introduced in 1.5. These are superior in their reusability. They are more flexible in how you can use them and in what you can pass into them. The only controllers you should be using are the ones in components.
Stop using $scope or $rootScope for anything. Used named controllers. This is the default setting for a component.
Consider ui-router over angular-route. It's just a lot better.
What is loadDirectives(app) doing?
Put a log statement in your RegistrationContoller.js and just verify that it isn't being called more than once. If it thinks RegistrationController is undefined after previously being defined, it just feels like it's being defined more than once.
Is there anything fishy in accountService.registerUser? Is this function forwarding you to the success screen? That's kind of weird... seems to me that the accountService.registerUser should return a promise, and the onSubmitClick should resolve the promise and forward the user.
Try forwarding back to the RegistrationController at different points in the code, and try to narrow down the exact point that it becomes undefined. I think that you have some code running somewhere that you don't think you do.

Angular Js controller not firing with routes

I am having a problem with AngularJS, where suddenly one of my controllers refuse to execure.
I load it with route, and i know the route is loaded as the html page attached is requested and inserted into the ng-view div i have.
My routes
when('/products/', {
templateUrl: 'app/components/products/products.html',
controller: 'productsController'
}).
when('/products/:productId', {
templateUrl: 'app/components/products/product.html',
controller: 'productController'
}).
I did not see any problems in my controller so i tried replacing all content with just a simple console log, and yet it do still not execute.
angular.module('DietPlanApp').controller('productsController',
['$scope', function ($scope) {
console.log('Get my products!');
}]);
My other controller productController workes just fine.
angular.module('DietPlanApp').controller('productController',
['$scope', '$routeParams', '$location', 'productService', 'userService',
function ($scope, $routeParams, $location, productService, userService) {
productService.getProduct(userService.getUserToken(), $routeParams.productId, function (data) {
if(data.result) {
$scope.product = transferToPortionSize(data.product);
} else {
$location.path("/products/");
}
});
$scope.save = function () {
productService.save(userService.getUserToken(), transferToUnitSize($scope.product));
$location.path("/products/");
};
$scope.delete = function () {
productService.deleteProduct(userService.getUserToken(), $scope.product.id);
$location.path("/products/");
};
}]);
And i have verified that the js files for productsController is loaded correctly in the HTML head, in the same way productController is.
It looks like the result of a namespace collision. You are overwriting productsController in public/app/components/users/authController.js.
It was probably the result of a copy/paste that your forgot to rename. That seems like the most likely culprit.
See the screenshot here.

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.

AngularJS $rootScope.$broadcast not working in app.run

I have the following code under my AngularJS .run which works perfectly on my local development machine but won't work when uploaded to my client server...after few tests it is obvious that by the time the controller is loaded the event is not triggered yet so most of the functions in the controller depending on this event do not work. Can someone please tell me what I am doing wrong here and how to fix it? Thanks
myApp.run(['AuthDataSvc', '$rootScope', function (AuthDataSvc, $rootScope) {
AuthDataSvc.getAuth().then(function(Token){
$rootScope.$broadcast('Token', Token);
}, function(status){
console.log(status);
});
}]);
You are always going to have a race condition. I have a couple alternatives you can do:
1) Use a service. I am not really a fan of this option because it leads to Spaghetti code. And most time you don't want the controller to run until you have logged on. I prefer option 2.
myApp.run(['AuthDataSvc', '$rootScope', function (AuthDataSvc, $rootScope) {
AuthDataSvc.getAuth(); /* no op we will use the service to determine logged in */
}]);
/* inside a controller */
if(AuthDataSvc.isLoggedIn()){
//do something.
}
2) Use a route.resolve. Resolves are defined on the route and the Controller will only load once it the promise has been set to resolved. I showed you an example for ui-router and ng-route you need to pick your poison. If you dont use ui-router you should consider it.
/* app.config ... route config.. */
var waitForLogon = {
UserToken: ["AuthDataSvc", function (AuthDataSvc) {
return AuthDataSvc.logon();
}]
};
//this is for ng-route
$routeProvider
.when('/Book/:bookId', {
templateUrl: '--',
controller: 'MyCtrl',
resolve: waitForLogon
})
//this is for ui-router
$stateProvider
.state('me', {
templateUrl: '--',
controller: 'MeCtrl',
resolve: waitForLogon
})
/* controller */
angular.module('yourapp')
.controller('MyCtrl', ["UserToken", ... , function(UserToken){
//User Token will always be here when your Ctrl loads.
});
/* service code -- */
angular.module('yourapp')
.service('AuthDataSvc', ["LogonModel", "$q", function(LogonModel, $q) {
this._q = null;
var that = this;
this._doAuth = function(){
this.getAuth().then(function(Token){ that._q.resolve(Token) }, function(error){that._q.reject(error);}
};
this.logon = function () {
if(!this._q){
this._q = $q.defer();
this._doAuth();// <-current auth do here, and resolve this._q when done
}
return this._q.promise;
};
});

Resources