$stateProvider.state('state1', {
url:'/state1/:param1/and/{param2:.+}',
templateUrl: 'state1.html',
controller: 'State1Controller',
});
I'm trying to make param2 required by using regex as seen above. If it's empty, then the default state should load:
$urlRouterProvider.otherwise("/");
$stateProvider.state('otherwise',{
url: '/',
templateUrl:'default.html'
});
Now the results:
state1/1/and/1 goes to state1. Good.
state1/1/and goes to otherwise. Good.
But,
state1/1/and/ goes to no state! Neither states are loaded. It's not redirecting back to /. What?!
How do I properly make a parameter required?
Angular js ui-router url parameters are optional by default. For your case above we could make use of $stateParams to check if the required parameter is defined or not. Please check the code below.
if ($stateParams.param2=== undefined) {
// Navigate to home.
$location.path('/');
}
Hope this would solve your issue. Thanks.
Related
Based on the documentation, angularjs ui-router url parameters are by default optional. So is there a way to create mandatory parameters? Like when the parameter is missing or null it will not proceed to the page?
Hope you can help me.
Thanks
Use UI Routers resolve to check if route params are missing.
//Example of a single route
.state('dashboard', {
url: '/dashboard/:userId',
templateUrl: 'dashboard.html',
controller: 'DashboardController',
resolve: function($stateParams, $location){
//Check if url parameter is missing.
if ($stateParams.userId === undefined) {
//Do something such as navigating to a different page.
$location.path('/somewhere/else');
}
}
})
Above answer prasents incorrect usage of resolve that will fail when code is minified even if annotated. Look at this issue I've spent a lot of time debugging this, because ui-router#0.4.2 won't warn you that resolve should be object.
resolve: {
somekey: function($stateParams, $location){
//Check if url parameter is missing.
if ($stateParams.userId === undefined) {
//Do something such as navigating to a different page.
$location.path('/somewhere/else');
}
}
If you need minification, ngAnnotate
I posted a question recently about how to set parameters in the URL with Angularjs so that they could be preserved on page reload. But it caused a problem with Google Maps.
I am using ngRoute to navigate around my application. And the problem that I've experienced with setting parameters in the URL, was that every time I would set a parameter (be it $location.search() or just a plain old window.location.hash='something'), the Google Maps map would get unloaded. I tried changing parameter names, because I thought Google Maps listens to some of those options by default. But that wasn't the case.
Once I got rid of the ngRoute code completely, and instead of the ngView directive, I included my pages with ng-include, the map didn't get unloaded anymore when I manipulated the parameters.
I'm not that good as to know exactly what or why is going on, but I would guess that ngRoute thinks it has to compile my template file again because "something" changed in the URL. So what I would like, is to explain to ngRoute somehow, that if the part after ? changed, then it shouldn't try to compile my template file again (and subsequently destroy the loaded Google Maps), because those are just my additional options. But if the part before ? changed, then that's fine, because then the page changed.
Or, is there another, better, more Angular-way of getting around this issue?
This is my ngRoute configuration:
app.config(function($httpProvider, $routeProvider) {
// Routing
$routeProvider.when("/", {
redirectTo: "/Map"
}).when("/Map", {
controller: "MapController",
templateUrl: "tpl/view/map.html"
}).when("/Table", {
controller: "TableController",
templateUrl: "tpl/view/items-table.html"
}).otherwise({
templateUrl: "tpl/view/404.html"
});
});
This is my code for changing pages:
$scope.navigate = function(location) {
$location.path(location);
};
And this is how I would set up a custom GET parameter, as per the code from my other Stackoverflow question:
var params = $location.search();
params.source = source.filename;
$location.search(params);
You're looking for the reloadOnSearch property.
app.config(function($httpProvider, $routeProvider) {
...
}).when("/Map", {
controller: "MapController",
templateUrl: "tpl/view/map.html",
reloadOnSearch: false
})
...
});
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
I have a link on my page (inside the scope of angular app 1) which changes the hash location
/app/#/location
I have another angular app (2) which is not reacting to the hash location change in the way I expect it to (ie by firing locationChangeStart, and changing state). I don't fully understand why. Anybody can explain this to me?
Edit 1: yes, there are two angular apps on the page, of different angular versions, both bootstrapped (sigh, don't ask). The ui-router configuration looks like this:
$urlRouterProvider.otherwise(($injector) => {
let $state = $injector.get("$state");
[... snip ...]
$state.go('list');
});
// Now set up the states
$stateProvider
.state('messaging', {
url: "/messaging/{param}",
templateUrl: "messaging.html",
controller: 'MessagingController'
})
.state('list', {
url: "/list",
templateUrl: "list.html",
controller: 'ListController'
});
Nothing really too fancy here, and before anybody asks, yes, I do need to check on a state in the otherwise.
The bootstrapping looks like this:
angular.element(document).ready(function() {
angular.element(document.getElementById('app-bootstrap')).prepend('<div ui-view></div>');
angular.bootstrap(document.getElementById('app-bootstrap'), ['app']);
});
Edit 2: this seems like it may be not an angular-related issue at all, as using the window 'hashchange' event directly doesn't seem to fire either; I've confirmed that window.onhashchange is the correct function.
(angular 1.4.7)
I am using UI Router with html5Mode enabled, states are loaded from JSON.
Expected behavior after F5 or when pasting URL is, respectively, having current state reloaded or navigating to the said state, instead the initial application state is loaded.
For e.g. root/parent/child gets redirected to root/.
By the way, navigating with ui-sref works fine.
So, how can the state be retained after page reload?
In order to retain the state of page after reload app, a url represent the state should be gave. when you include ui-route module, url will be parsed and sent to corresponding state. You don't need to parse the url handly in most cases, ui-route born to do this.
Please can you post your code here? Specifically the $stateProvider.
This is an example of a correct $stateProvider and it works fine:
$stateProvider.state('main.admin', {
url: '/admin',
resolve: {},
views: {
'main-content#main': {
controller: 'AdminController as admin',
templateUrl: 'main/admin/admin.tpl.html'
}
}
});
Seems a bit hacky, but works for now.
app.run(['$location', '$state', function ($location, $state) {
function stateFromUrl () {
var path = $location.path(),
hash = $location.hash();
// do JSON states map parsing and find a corresponding to the URL state
return state;
}
if (stateFromUrl) {
$state.go(stateFromUrl);
} else {
$state.go('home'); // initial state
}
}]);
I want to show 404 error page, but also I want to save wrong url in location.
If I'll do something like that:
$urlRouterProvider.otherwise('404');
$stateProvider
.state('404', {
url: '/404',
template: error404Template
});
url will change to /404. How I can show error message on wrong urls without changing actual url?
There is solution for this scenario. We'd use 1) one ui-router native feature and 2) one configuration setting. A working example could be observed here.
1) A native feature of ui-router state definitions is:
The url is not needed. State could be defined without its representation in location.
2) A configuration setting is:
otherwise() for invalid routes, which parameter does not have to be a string with default url, but could be a function as well (cite):
path String | Function 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
Solution: combination of these two. We would have state without url and custom otherwise:
$stateProvider
.state('404', {
// no url defined
template: '<div>error</div>',
})
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
state.go('404');
return $location.path();
});
Check that all in this working example
As of ui-router#0.2.15 you can use $state.go() and send option not to update the location:
$urlRouterProvider.otherwise(function($injector) {
var $state = $injector.get('$state');
$state.go('404', null, {
location: false
});
});