AngularJS (ionic) - $routeParams argument from URL - angularjs

I'm new with AngularJS and I'm wondering about the reading-limits of the a $routeParams-Service... reading the URL-arguments.. whether f.i. "/" - a slash would disrupt the workflow...? .. or is there a usable workaround?
Codeexample: (partly from Ionic Starter App)
App.js
.config(function ($stateProvider, $urlRouterProvider, USER_ROLES) {
$stateProvider
.state('main.product/:productId', {
url: 'main/product/:productId',
views: {
'menuContent': {
templateUrl: 'templates/product.html',
controller: 'productIdCtrl'
}
}
})
.controller('productIdCtrl'),
function($scope, $location, $routeParams, ProductDataService){
var pId = $routeParams.productId; // Reading productId from URL
}
Inside the database its sadly possible to use "/" - slash as an "productId"-Name. Probably some other special characters... which I have yet to explore.. so I dont think this will work..?
So my question is, where are the limits .. which characters would need a major workaround.
(In Order to read Data from the database I should probably use get/post with json.php ... but I'm not there yet (but I surely like advice :D)
It is supposed to simply read data from the database.. with a small searchengine which is already realized on another system and I just need to 'get' and display the data...)

Here correctly
...
.state('main.product.id', {
url: 'main/product/:productId',
views: {
'menuContent': {
templateUrl: 'templates/product.html',
controller: 'productIdCtrl'
}
}
})
...
.controller("AppController", function($scope, $state){
$scope.openProduct = function(){
$state.go('main.product.id', {productId: 1});
};
});

Related

Angular state : pass multiple parameter without changing url querystring to controller

I want to send a parameter from app.run to my loginController. Because, I call a state.go() from the $rootScope.$on() defined inside the app.run.
app.run('$rootScope', '$state', '$stateParams',function($rootScope, $state, $stateParams(){
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on('unauthorized_access', function (event, args) {
$state.go("page.login", {'error': args.error,'msg': args.msg});
});
}]);
I have
app.config(['$stateProvider','$urlRouterProvider',function($stateProvider, $urlRouterProvider, $httpProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
// some parts omitted...
.state('page.login', {
url: '/login',
views: {
'page': {
templateUrl: 'app/landingPage/login.html',
controller: 'loginController',
params: {obj : {error : null, message: null} }
}
}
});
}]);
and I want to pass parameters to the loginController from app.run, through $state.go() during transition.
$state.go("page.login", {'error': err,'message': msg});
and in my controller, this is how I am trying to receive the params...
app.controller('loginController',['$scope', '$state', '$stateParams', function($scope, $state, $stateParams){
console.log($stateParams.obj);
}]);
I do not want to change the url to >> url: '/login/:params' etc. in stateProvider
I referenced this page : stackoverflow example
but,was not helpful. Any help is appreciated. Apologies for my poor communication.
After a long research, I ended up with weird solution. I still doubt, whether this is even a solution. However, it does work for me.... I made a hack of ui.router LOL ....
I am using Angular ui-router version v0.2.18. and there at line no. 3160, they have put a line of code like :
// Store the hash param for later (since it will be stripped out by various methods)
var hash = toParams['#'];
and in line no. 3223 they have
if (shouldSkipReload(to, toParams, from, fromParams, locals, options)) {
if (hash) toParams['#'] = hash;
So, I thought of passing my object with a '#' key like this
.state('page.login', {
url: '/login',
views: {
'body#page': {
templateUrl: 'app/landingPage/login.html',
controller: 'loginController',
params: {'#' : null},
}
},
authenticate: false
});
and like this
$rootScope.$on('unauthorized_access', function (event, args) {
$state.go("page.login", {'#' : {'error': args.error,'msg': args.msg}});
});
and surprise, it worked.....
I got the object logged in console : console.log($stateParams['#']);
I know the solution is cunning[udayip as in malayalam]... but then it worked for me... I will not mark this as an answer. So, I request some angular experts to provide a real solution. If some experts say, this can be a solution, I will mark this as the answer.

Redirect after login AngularJS Meteor

I'm trying to redirect after login to a specific page in Meteor using AngularJS. But somehow it is not working. After login Meteor.user() is returning null. Because of this every time it is routing to messages page only. I have seen this example from one of the forums and developed on top of that.
angular.module("jaarvis").run(["$rootScope", "$state", "$meteor", function($rootScope, $state, $meteor) {
$meteor.autorun($rootScope, function(){
if (! Meteor.user()) {
console.log('user');
if (Meteor.loggingIn()) {
console.log('loggingIn ' + Meteor.user()); -- returning null
if(Meteor.user()) {
$state.go('onlineusers');
} else {
//On login
$state.go("messages");
}
}
else{
console.log('login');
$state.go('login');
}
}
});
}]);
Routes declared as below.
angular.module('jaarvis').config(['$urlRouterProvider', '$stateProvider', '$locationProvider',
function($urlRouterProvider, $stateProvider, $locationProvider){
$locationProvider.html5Mode(true);
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'login.ng.html',
controller: 'LoginCtrl'
})
.state('onlineusers',{
url: '/onlineusers',
templateUrl: 'client/onlineusers/onlineusers.ng.html',
controller: 'OnlineUsersCtrl'
})
.state('messages', {
url: '/messages',
templateUrl: 'client/chats.ng.html',
controller: 'ChatCtrl'
})
});
$urlRouterProvider.otherwise("/messages");
}]);
Logging using below snippet of code.
<meteor-include src="loginButtons"></meteor-include>
Michael is probably right about the root cause of the problem, but I think that a better alternative is provided by the the authentication methods of Angular-Meteor.
What you are going to want to do is to force the resolution of a promise on the route. From the Angular-Meteor docs (i.e. a general example...):
// In route config ('ui-router' in the example, but works with 'ngRoute' the same way)
$stateProvider
.state('home', {
url: '/',
templateUrl: 'client/views/home.ng.html',
controller: 'HomeController'
resolve: {
"currentUser": ["$meteor", function($meteor){
return $meteor.waitForUser();
}]
}
});
Your specific code would look something like:
angular.module('jaarvis').config(['$urlRouterProvider', '$stateProvider', '$locationProvider',
function($urlRouterProvider, $stateProvider, $locationProvider){
$locationProvider.html5Mode(true);
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'login.ng.html',
controller: 'LoginCtrl'
})
.state('onlineusers',{
url: '/onlineusers',
templateUrl: 'client/onlineusers/onlineusers.ng.html',
controller: 'OnlineUsersCtrl',
resolve: {
"currentUser": ["$meteor", function($meteor){
return $meteor.waitForUser();
}]
}
})
.state('messages', {
url: '/messages',
templateUrl: 'client/chats.ng.html',
controller: 'ChatCtrl',
resolve: {
"currentUser": ["$meteor", function($meteor){
return $meteor.waitForUser();
}]
}
})
});
$urlRouterProvider.otherwise("/messages");
}]);
And then on your ChatCtrl and OnlineUsersCtrl controllers, you would add currentUser as one of the variables to inject, like:
angular.module("rootModule").controller("ChatCtrl", ["$scope", "$meteor", ...,
function($scope, $meteor, ..., "currentUser"){
console.log(currentUser) // SHOULD PRINT WHAT YOU WANT
}
]);
You might also want to consider the $meteor.requireUser() promise as well, and then send the user back to the login page if the promise gets rejected. All of this is documented very well on the angular-meteor website.
Good luck!
It could be that the user object hasn't loaded yet. You can try:
if ( Meteor.userId() ) ...
instead

Angular ui.router. Deep nested routes

Here is an example to check http://embed.plnkr.co/uVMlkk/preview
When we navigate to 'page2' route there is a 'hey, I'm a subroute' note.
But once we navigate anywhere else that note will disappear forever.
The goal is to make some nested states to be shown right away (as a default ones).
I assume there should be some cases using $state.go(), but can't figure it out so far. Any help is highly appreciated.
State definition snippet:
.state('root.page2.tab', {
url: '/:tabId',
templateUrl: 'tpl.page2.tab.html',
controller: 'Page2TabController'
})
.state('root.page2.tab.subroute', {
url: '',
templateUrl: 'tpl.page2.tab.subroute.html'
})
the content of the 'tpl.page2.tab.subroute.html':
hey, I'm a subroute
related controller:
.controller('Page2TabController', ['$scope', '$state', function($scope, $state) {
$scope.tabId = $state.params.tabId;
$state.go('root.page2.tab.subroute');
}])
There is a fixed version.
I removed the url from the 'root.page2.tab.subroute'
.state('root.page2.tab.subroute', {
//url: '',
templateUrl: 'tpl.page2.tab.subroute.html'
})
And because the parent has defined paramater tabId:
.state('root.page2.tab', {
url: '/:tabId',
templateUrl: 'tpl.page2.tab.html',
controller: 'Page2TabController'
})
We have to pass that param inside of the redicrection:
.controller('Page2TabController', ['$scope', '$state', function($scope, $state) {
$scope.tabId = $state.params.tabId;
// instead of this
// $state.go('root.page2.tab.subroute');
// we need this
$state.go('root.page2.tab.subroute', $state.params);
}])
Check the working, fixed version here
ANOTHER approach - using redirectTo - there is a working plunker
One way, inspired by this:
Redirect a state to default substate with UI-Router in AngularJS
could be to add a very smart but small redirect code snippet:
.run(['$rootScope', '$state', function($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function(evt, to, params) {
if (to.redirectTo) {
evt.preventDefault();
$state.go(to.redirectTo, params)
}
});
}])
And adjust our state like this:
.state('root.page2.tab', {
url: '/:tabId',
templateUrl: 'tpl.page2.tab.html',
controller: 'Page2TabController',
redirectTo: 'root.page2.tab.subroute',
})
Check it here
There is a trick how to handle scenarios:
Parent should trigger some action in case that
it is accessed, or
its reached again, when navigating back from child in a parent state
In that case, we can use the "target (ui-view) for a child" as a place where sits the special view, with special controller. This will be
injected into that position once parent is created and
re-injected into that position again, once child is left. In that case, it will be re-init.
Enough explanation. There is a working plunker. There is adjusted state:
.state('root.page2', {
url: '/page2',
views: {
'content#root': {
templateUrl: './tpl.page2.html',
controller: 'Page2Controller'
},
'#root.page2': {
template: '<div></div>',
controller: 'RedirectorController'
}
}
})
So, now we can do some magic inside of our 'RedirectorController'
.controller('RedirectorController', ['$scope', '$state',
function($scope, $state) {
$state.go('root.page2.tab', { tabId: $scope.activeTabId });
}])
Check it in action here
Read more about what that new view/controller get from the other (Scope Inheritance by View Hierarchy Only) one here
Nested states or views for layout with leftbar in ui-router?
How do I share $scope data between states in angularjs ui-router?

URL not finding state ( ui.router and angularjs)

I have the following states:
$stateProvider.
state('candidates', {
abstract: true,
url: '/candidates',
templateUrl: '/Scripts/App/js/Views/candidates/candidates.html',
controller: 'candidatesTableController'
}).
state('candidates.item', {
url: '/{item:[0-9]{1,4}}',
templateUrl: '/Scripts/App/js/Views/candidates/candidate.html',
controller: 'candidatesDetailController'
}).
state('candidates.item.details', {
url: '/details',
templateUrl: '/Scripts/App/js/Views/candidates/partials/generalDetails.html',
controller: function($scope, $stateParams) {
$scope.item= $stateParams.item;
}
}).
state('candidates.item.edit', {
url: '/details/edit',
templateUrl: '/Scripts/App/js/Views/candidates/partials/form.html',
controller: function($scope, $stateParams) {
$scope.item = $stateParams.item;
}
}).state('candidates.item.photo', {
url: '/details/photo',
templateUrl: '/Scripts/App/js/Views/candidates/partials/updatePhotoID.html',
controller: function($scope, $stateParams) {
$scope.item = $stateParams.item;
}
});
Here my urlRouterProvider:
$urlRouterProvider
.when('/candidates/:item', '/candidates/:item/details')
.otherwise("/");
When I use ui-sref everything work fine but when i using the actual url, it never can find the following url:
"/#/candidates/4/details"
it redirect to the root ("/#/")
I can't figure out why?
Thanks
I created a plunkr with your routes defined here:
http://run.plnkr.co/Sn3s7ooM6MOSxQnB/#/candidates/4/details
Code visible here:
http://plnkr.co/edit/wArFenIZ7j3WczUhtJO6
Notice that the first link in this answer takes you right to the details page for a candidate item. Maybe you can figure out from my simplified code what it is that you need to change to achieve the same behavior.
Also, I noticed that your redirect doesn't work (the second nav item in my plunker allows you to go to this state without a redirect; try clicking it yourself):
.when('/candidates/:item', '/candidates/:item/details')
This redirect will work if you set the candidates.item state to be abstract. Maybe this is what you want.
See this in action here: http://plnkr.co/edit/y9LI0OKGMStVnMY2NX5q
Code visible here: http://plnkr.co/edit/y9LI0OKGMStVnMY2NX5q
I hope that helps

UI-Router using routes within a Section of a Site

The site I'm building already has URL's built up using MVC. So for example /Account goes to a page, /Customers goes to a page, and /Quotes goes to a page. On the /Quotes page I have a multi-step wizard which I want to use Ui-Routing on. See my app.js below, this all works.
So my URL becomes /Quotes#newmodel, /Quotes#customer, etc. A different #{value} for each step on the wizard. The problem is that the .otherwise affects all other areas of the site. So if I'm going to /Account, I get the url /Account#wizard. I do not want this to occur anywhere other than on the /Quotes page. Is there anything I can do with the URL matching so I can remove the .otherwise?
'use strict';
var myApp = angular.module('myApp', ['ui.router']);
myApp.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/wizard");
$stateProvider
.state('wizard', {
url: '/wizard',
templateUrl: 'Scripts/templates/wizardLayout.html',
controller: 'wizardNavigationCtrl'
})
.state('wizard.newmodel', {
url: '/newmodel',
templateUrl: 'Scripts/templates/wizardModel.html',
controller: 'wizardModelCtrl'
})
.state('wizard.other', {
url: '/other',
templateUrl: 'Scripts/templates/wizardOther.html',
controller: 'wizardOtherCtrl'
})
.state('wizard.customer', {
url: '/customer',
templateUrl: 'Scripts/templates/wizardCustomer.html',
controller: 'wizardCustomerCtrl'
})
.state('wizard.shipping', {
url: '/shipping',
templateUrl: 'Scripts/templates/wizardShipping.html',
controller: 'wizardShippingCtrl'
})
.state('wizard.review', {
url: '/review',
templateUrl: 'Scripts/templates/wizardReview.html',
controller: 'wizardReviewCtrl'
});
}]);
I'm also interested in how I can cause the route to load the layout and then by default go to the wizard.newmodel route (though this may be a separate question). Basically the same behavior as if I click on an:
<a sref-ui=".newmodel">
I removed the $urlRouterProvider.otherwise("/wizard") in the app.js.
Instead I added a controller to the main /Quote page that redirects the $location.url to '/wizard'. Below is the code.
myApp.controller('wizardCtrl', ['$location', function ($location) {
$location.url('wizard')
}])

Resources