Conditional "otherwise" routing in Angular - javascript

I'm familiar with the "$urlRouterProvider.otherwise('{route here}')" syntax in angular to use as catch all in Angular UI-Router.
What I'm wondering is - is there a way to do conditional "otherwise" routing based on the parent state of when the route is entered incorrectly?
For instance, suppose that I have the following configuration:
$stateProvider
.state('core', {configuration here})
.state('core.page1', {configuration here...})
.state('dashboard', {configuration here})
.state('dashboard.page1', {configuration here})
$urlRouterProvider.otherwise('/core/page1');
What I'd like to have happen is that anytime a route is entered in that has "/core/{route here}",
if it doesn't match any of the current states, to route back to '/core/page1',
and anytime a route is entered that has "/dashboard/{route here}" that doesn't match any of the current states, to route back to "/dashboard/page1".
Anyone have experience doing this, or an idea of how I could accomplish it? Is there anything built in to Angular that allows for this type of behavior?
Thanks in advance!

As shown here
How not to change url when show 404 error page with ui-router
The .otherwise() does not have to be a string (url)... it could be a smart decision maker:
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
if(....)
state.go('core');
else(...)
state.go('dashboard');
...
return $location.path();
});
The doc:
$urlRouterProvider.otherwise(rule)
Defines a path that is used when an invalid route is requested.
string - The url path you want to redirect to or a function rule that returns the url path.
The function version is passed two params: $injector and $location services, and must return a url string.

Related

JavaScript | AngularJS | UI-Router: $urlRouterProvider Redirect With Parameters

The Problem...
The Implementer should have the ability to write simple redirects using $urlRouterProvider.when to invoke another state with the same, expected URL-parameters:
$urlRouterProvider.when('/hook/route', '/that/other/route');
This should provide the correct $sateParams needed for the target state. For example, if the URI /hook/route?token=X is called, the target state should have $stateParams.token === 'X' -- given that this parameter is configured within the $stateProvider ({... url: '/that/other/route?token' ...});
The conventional way [in Stackoverflow-land] looks like the following:
$urlRouterProvider
.when('/hook/route', redirect)
.otherwise('/');
function redirect($state, $stateParams) {
$state.go('app.otherState', { token: $stateParams.token });
}
This seems very overkill for a simple redirect-with-parameters action -- especially if many redirects are needed.
The answer I'll provide below shows a very-low-overhead approach, which unfortunately, has not been spot-lighted in other StackOverflow threads regarding this topic...
... Solution
Match your URI's parameters against those expected by your target state:
$urlRouterProvider
.when('/hook/route?token', '/route?token')
.otherwise('/');
Cheers!

Parameters in URL using Angular's UI-Router, issue with .otherwise

I want to search on my page. Actually, my code is
$stateProvider
.state('aaa', {
url: '/aaa',
templateUrl: 'client/parties/views/aaa.ng.html',
controller: 'Aaa'
})
$urlRouterProvider.otherwise("/default");
And now, I want to search on my page, but the params MUST working with the URL.
How to use params when I have $urlRouterProvider.otherwise?
Actually, everything after /aaa/ in URL causes redirect to /default.
Important thing: I have more than 20 parameters, but when there're not selected, I don't want to pass it via URL. This is important because I think I can't do something like url: '/details/:param1:param2:param3:param4',
Can you help me?
Looking at the documentation for ui-router, it doesn't seem like it is possible to not have it redirect without having at least one parameter defined on the state's route.
To accomplish what you want, I think the best is to use a catch all parameter of some sort. It's either that, restricting deep-linking, or reducing the amount of parameters and manually defining it.
Define a catch all parameter as shown below. In this case the parameter is path redirects will not take place if there is nothing after "/files/":
'/files/{path:.*}' - Matches any URL starting with '/files/' and captures the rest of the path into the parameter 'path'.
'/files/*path' - Ditto. Special syntax for catch all.
Define one parameter on a new route, and then split the one parameter into multiple parameters in the controller.

Getting part of a URL path via Angular.js

I want to get part of a path in URL via Angular.js and i found solution:
http://mywebsite.com/one/HEREiWANT/three
first i do this:
app.config(function($locationProvider){
$locationProvider.html5Mode(true);
});
then i define my controller like this:
app.controller("mainCtrl", function ($scope,$location) {
//...
}
then with this method i can get what i want and it works!:
$scope.getURLPart = function () {
return pId = $location.path().split("/")[3]||"Unknown";
};
But this has a huge problem, right now after this changes, all of my linkes in my website doesn't work. When i click on a link, address in browsers address bar changes but i stay at the same page and redirection process doesn't happen. Why? How i can achieve what i want without with this problem?
In your state if your using state and yor passing params to your state then you can use
$stateparams to get the params
$stae.go("particular state name") to route to states

AngularJS - Handling empty Params

I'm using UI-Router and all is working great but I'd like to prevent the possibility that someone could access a page with empty Params. Is there a "best" method for preventing something like... '/person//info' where it would normally expect an id for the person like '/person/23/info'. My setup is as follows...
.state('person',{
abstract:true,
url:'/:id/',
templateUrl: '/assets/components/views/person.html',
controller: function($stateParams){
console.log($stateParams.id);
}
})
The reason this is a real pain is because if you hit the path '/person//info', it will redirect to /person/info essentially breaking the app

Pass URL to as $routeParam in AngularJS app

How can I pass actual URL (with slashes, commas, etc.) as a $routeParam to AngularJS App?
this will work:
http://paprikka.github.io/le-bat/#/preview/asdadasda
this won't:
http://paprikka.github.io/le-bat/#/preview/http://page.com
neither will this:
http://paprikka.github.io/le-bat/#/preview/http%3A%2F%2Fpage.com
or this:
http://paprikka.github.io/le-bat/#/preview/?url=http%3A%2F%2Fpage.com
Details
AngularJS routing mechanism by its design does not allow to pass strings with slashes as query parameters. I can understand the reasoning behind this decision - we don't want to create a stateless server here.
However, there are still cases when using different separators or regular expressions in routes might be necessary.
I wanted to create an app that takes a url hash string parameter and loads its content to an iframe (link here). Routes are set up in pretty standard way (I'm using Coffeescript, but this snippet does not differ from pure js):
$routeProvider
.when('/preview/:src', {templateUrl: 'partials/preview.html',
controller: 'PreviewCtrl'})
.when('/preview', {templateUrl: 'partials/preview.html',
controller: 'PreviewCtrl'})
Of course, I can load url from hash before AngularJS gets bootstrapped and then pass it to the library, but it would be nice if I could also update current route parameter when changing data in scope - that's why I think it's much better not to avoid AngularJS API.
Using $routeProvider in Angular 1.2, you can pass in a url if it's at the end of the path by adding an asterik to the pattern. The following should work whether or not you URLComponentEncode the url.
The route:
angular.module('angularApp', ['ngRoute'])
.when('/frame/:picture_url*', {
templateUrl: 'views/frame.html',
controller: 'PictureFrame'
});
The controller:
.controller('PictureFrame', function($scope, $routeParams, $sce){
//whitelist the URL
$scope.picture_url = $sce.trustAsResourceUrl($routeParams.picture_url);
});
Then in your template:
<iframe ng-src="{{picture_url}}"></iframe>
Ok, I've managed to find a solution working with current stable version (#1.0.7).
Current way of handling this problem will involve $route-related events, parsing angular-incompatible urls on the fly and handling them via an additional service working in a similar way as $http interception.
You can see working code examples here: http://embed.plnkr.co/fIA2xj/preview
Main steps
pass an angular-incompatible url as usual, eg. go to site.com/url/http://site.com
listen to a $routeChangeStart event and extract correct url parameter for paths beginning with /url/
encode the correct url parameter to an angular-compatible form (in this particular case, I use base64). Don't use encodeURIComponent, because angular will treat as any other url
redirect to another route with your business logic, eg. site.com/parsed-url/BASE64_GOES_HERE
decode the URL in the controller and use it as usual :)
Code
Create angular app module as usual
angular.module('routes',[]).config([
'$routeProvider',
function($routeProvider){
$routeProvider
.when('/test', {templateUrl: 'test.html'})
// This one is important:
// We define a route that will be used internally and handle
// parameters with urls parsed by us via the URLInterceptor service
.when('/parsed-url/:url', {templateUrl: 'url.html', controller:'URLCtrl'})
.when('/', {redirectTo: '/test'})
.otherwise({templateUrl: '404.html'});
}
])
URL Interceptor service (singleton)
.service('URLInterceptor', function($rootScope, $location){
// We listen to $routeChangeStart event and intercept it if
// the path matches our url scheme. In this case, every route
// beginning with /url/ will be caught
$rootScope.$on('$routeChangeStart', function(e, next, current){
// $location.path does change BEFORE actual routing happens,
// so in this case we get parsed new location object
// for free.
// To be hones, a better way of handling this case might be using
// $locationChangeStart event instead, but it would require us to parse urls
// manually.
var path = $location.path();
// check if string begins with '/url/'
var matcher = path.slice(0,5);
var cleanPath = '';
if (matcher === '/url/'){
// Yes it does, yay!
// Remove leading '/url/' to extract the actual parameter
cleanPath = path.slice(5);
// Encode our url to a safe version. We know that encodeURIComponent won't
// work either, so a good choice might be base64.
// I'm using https://code.google.com/p/javascriptbase64/downloads
$location.path('/parsed-url/' + Base64.encode(cleanPath));
// Prevent default event execution. Note that, it won't cancel related $location Events
e.preventDefault();
}
});
return {
decode: Base64.decode,
encode: Base64.encode
}
})
Controllers
// Main application controller
// We instantiate our URLInterceptor service here
.controller('AppCtrl',function($scope, $location, URLInterceptor){
$scope.navigateTo = function (path) {
$location.path('/url/' + path);
}
})
.controller('URLCtrl', function($scope, $routeParams, URLInterceptor){
$scope.url = URLInterceptor.decode($routeParams.url);
});
Two things you should remember:
Although I tried to create a solution as clean as possible, usually passing the data this way to angular isn't considered a good practice, so try not to use it unless you really need to.
You can handle this issue with only one route. I just find it cleaner this way.
I have a solution but I don't know if it will help you. From Angular documention http://docs.angularjs.org/api/ng.$location $location has a function search(search, paramValue)
To pass the parameter:
parameter = encodeURIComponent url
$location.search({ yourURLParameter: parameter }).path('/preview')
To read the parameter:
url = decodeURIComponent $location.search().yourURLParameter
Of course you need to inject $location dependency
I have mixed search params with routes. Your search needs to come before your routes.. specifically for older browsers. I think ie7 blows up if its not url/?search/#/hash
Try this format:
domain.com/?my=params&another=param/#/my/hashes

Categories

Resources