The ui-router in our angular application always appends "#app" to the URLs in our app, which clearly is not desired behaviour. This also has the side-effect, that when you use the browser navigation (back and forward), you'll need two clicks to actually switch the page.
AngularJS version: 1.2.29
ui-router version: 0.2.10
The browser history looks like so:
http://localhost:8080/app/#/modulename
http://localhost:8080/app/#/modulename#app <- unnecessary step
http://localhost:8080/app/#/anothermodule
http://localhost:8080/app/#/anothermodule#app <-unnecessary step
... and so on.
We already tried switching to ui-router's html5mode, but this just omits the first hash-sign in the URL and doesn't have any effect on anything else.
This is our stateProvider
$stateProvider
.state('app', {
abstract: true,
url: '/',
// parent: true,
templateUrl: CONFIG.baseUrl + '/js/modules/Core/View/app.html',
})
.state('access.404', {
url: '/404',
templateUrl: 'tpl/page_404.html'
});
Related
I'm working on an Angular 1.6.1 web-application with Angular Material and ui-router modules installed.
Navigating from state to state is working fine but when the browser back button is pressed the URL is changing but the state is not (the view stays the same)! I get the following error in the console log:
TypeError: a.indexOf is not a function
at f (angular.js:438)
at m (angular.js:438)
at Object.z.transitionTo (angular.js:438)
at Array.<anonymous> (angular.js:438)
at Object.invoke (angular.js:39)
at g (angular.js:438)
at angular.js:438
at b (angular.js:438)
at n (angular.js:438)
at m.$broadcast (angular.js:146)
The $stateChangeStart is not even reached.
So it seems like there is something happening to the browser history stack.
A couple of days ago everything worked fine, did not change anything since then (well, not according to my git log).
My $stateProvider config is divided over different files, the first file looks likes this:
$stateProvider
//Main states
.state('main', {
abstract: true,
controller: 'MainController',
template: '<div ui-view flex layout="column"></div>'
})
.state('null', {
parent: 'main',
url: '/',
controller: function($state){
$state.go('login', {}, {location: "replace", reload: true});
}
})
//main loggedin state loading main loggedin view
.state('logged-in', {
parent: 'main',
abstract: true,
templateUrl: COMP_DIR + 'core/logged-in/logged-in.view.html',
controller: 'LoggedInController',
controllerAs: 'vm'
})
.state('no-enterprise', {
parent: 'logged-in',
abstract: true,
template: '<div ui-view flex layout="column"></div>',
controller: 'NoEnterpriseController'
})
After this configuration I include a couple of routing files for each module of the application. After that I add the last routing file like this:
$stateProvider
//main enterprise state
.state('enterprise', {
parent: 'logged-in',
url: '/{slug}',
controller: 'EnterpriseController',
controllerAs: 'vm',
template: '<div ui-view flex layout="column"></div>'
})
//states inside enterprise state
.state('dashboard', {
url: '/',
parent: 'enterprise',
title: 'Dashboard',
templateUrl: COMP_DIR + 'dashboard/dashboard.index.view.html',
controller: 'Dashboard.DashboardController',
controllerAs: 'vm'
})
The state changes are being triggered by adding a simple ui-sref to an element and that is working fine, but i'm not able to go back with the back button of the browser.
Does anybody have an idea why this error is popping up and the back button is therefore not working properly?
Thanks in advance!
Edit: Additionally, when I refresh the application (pressing F5) back button is working until I navigate forward one step, then I get the same error trying to navigate forward in the history stack.
I solved the problem. There was an error in the $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams) {} function.
I tried to compare the toState.name to something undefined.
Which was weird because the error occurs before the state change. So if you have a error while changing states be sure to check your $stateChangeSuccess event handler ;)
I have an angular app where I am using ui-router module. I am storing a "page" in database with URL and content. I also have some other states/URLs that have their own template. For example:
$stateProvider
.state('landing', {
url: '/',
templateUrl: 'landing-page.html'
})
.state('admin', {
url: '/admin',
templateUrl: 'admin.html'
})
.state('user', {
url: '/user',
templateUrl: 'user.html'
})
I want to define a state for the pages using something like
.state('page',{
url: '??',
templateUrl: 'page.html'
})
What should be in the url above if my page is dynamically stored in database with a URL/slug and content. How can I add the URL/slug here ? If I try this below:
.state('page', {
url: '/{path:.*}',
templateUrl: 'page.html'
})
Then it routes every page including the other states to the same template. I can always prefix the URL with something like /page but I don't want to do that. I want to be able to load the page as :
www.mysite.com/page-1
www.mysite.com/whatever-url
etc
Never mind. I figured this out. The trick was more about using regular expression. Here is my solution
.state('page', {
url: '/{path:(?!admin|user)[a-z0-9\-]+}',
templateUrl: 'page.html'
})
This will ignore routes starting with /admin and /user which we want first. Then, it will check if the url has at least 1 character.
I am writing a CRUD app with AngularJS + UI Router.
I want to be able to parse the current location in the browser URL and determine if a ui-router state should be applicable for the current url.
In these sample routes, is there some way to do the if and unless clauses?
(url in browser address bar is http://example.com/notes/1/edit_me)
$stateProvider.state("root", {
url: "",
unless: $location.matches(/\edit_me/)
})
$stateProvider.state("edit", {
url: "/edit",
if: $location.matches(/\edit_me/)
//
})
UPDATE 1
The reason I want to do the above:
Say I am at http://example.com/notes. The routes is
$stateProvider.state("root", {
url: "",
})
However, with the same above ui.route state, when I am at url http://example.com/notes/edit, the root is now "/notes/edit" instead of "/notes"
UPDATE 2
#adam, more explanation of what I am trying to accomplish:
I will try to explain: in your code, for your home state, the (ui.router's) url is / (aka hash syntax #!/)
However, the URL in browser address bar looks like http://example.com/notes/ in one case and http://example.com/notes/edit in another case. (note that the URLs do not contain any #! portion since we have just navigated to the page)
Now the home's / is going to match in both cases of above URL.
But since the second URL ends in notes/edit, I want that the home for this URL should be #!/edit, and not #!/.
Basically I am trying to mix server-side rendered pages (/notes and /notes/edit are rendered by server, not AngularJS)
and client side routing so that no matter which URL we are at, the client can figure out which (ui.router) route applies to the current URL.
Make sense?
Sorry i don't really understand your needs but here's an example of use of ui-router:
$stateProvider
.state('home', {
url: '/',
templateUrl: 'app/main/index.html',
controller: 'MainCtrl'
})
$stateProvider
.state('edit', {
url: '/edit',
templateUrl: 'app/edit/edit.html',
controller: 'EditCtrl'
})
$stateProvider
.state('edit.note', {
url: '/note',
templateUrl: 'app/edit/note.html',
controller: 'NoteCtrl'
});
$urlRouterProvider.otherwise('/');
i'm not sure if a copy paste will work, but try to adapt it with your case. Hope it will help.
Edit:
I'm afraid that i can't help you more than that. The design of your app with rendered page without angular sounds really special.
Have you tried the example i provide you? If yes, hav you simply format the url by addind
" #!/ " where you need it.
For example:
$stateProvider
.state('edit', {
url: '#!/edit', //or something like, url:'/#!/edit'
templateUrl: 'app/edit/edit.html',
controller: 'EditCtrl'
});
Check this link also may be it will help you:https://github.com/angular-ui/ui-router/issues/372
ui-sref may help you
But the place to see usefull example for ui-router it's his own doc.
https://github.com/angular-ui/ui-router
and here:
http://angular-ui.github.io/ui-router/site/#/api/ui.router
When using nested states from UI Router, this will only work if you navigate the page through the nest. i.e.:
If I have
.state('home', {
url: '/',
templateUrl: 'home.html'
...
})
.state('home.page', {
url: '/page',
templateUrl: 'page.html'
...
})
.state('home.page.sub' , {
url: '/page/sub',
templateUrl: 'sub.html'
...
})
Now the problem is if I directly visit /page/sub without going to / and then click on link to go to /page and finally navigate to /page/sub, then the linking is not proper and the elements of the page will not fully load.
How can I fix this linkage issue?
Almost the same issue could be found here:
angular ui-router parent url set to /
I've created plunker showing a working example. The trick here is to use one of the ui-router features:
Absolute Routes (^)
As we can observe in the plunker/code snippet below, we have to adjust the state definition. We need to be able to distinguish among states just by the passed url route
1) first level, a home state, will be used for path '/'
2) second level, a page state, won't be using the parent url, but will be defined as '/page' ... starting from the root.
Therefore ui-router will be able to decide which state to issue. Without the Absolute Routes (^) we would need combine parent and child: '//page' would be the proper route...
.state('home', {
url: '/',
templateUrl: 'home.html'
...
})
// here is the change, see the ^
.state('home.page', {
url: '^/page',
templateUrl: 'page.html'
...
})
.state('home.page.sub' , {
url: '/page/sub',
templateUrl: 'sub.html'
...
})
And now, each state could be accessed as
<li><a ui-sref="home">Home</a></li>
<li><a ui-sref="home.page">- Page</a></li>
<li><a ui-sref="home.page.sub">- - Sub</a></li>
And its url will be:
#/ -- this is home
#/page -- the page, in fact starting from root
#/page/sub
Working plunker: plunker
I'm using ui-router in Angularjs and I have the following routes (as part of my app.js file):
...
$urlRouterProvider.otherwise('/dashboard');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'views/home.html',
data: { public: true }
})
.state('login', {
url: '/login',
templateUrl: 'views/login.html',
data: { login: true }
})
...
I have decided to keep the # in my routes because ui-router doesn't work too well with the html5 setting for routing without the hash.
Question: When I navigate to localhost:8080/ I would expect my home state to kick in but it goes to /dashboard (the otherwise route). I can only access the root of my site with localhost:8080/#/ - is this expected behaviour?
Not the answer for the question, but you might want to take a look at http://angular-route-segment.com for this case, as it works on top of built-in ngRoute module which plays well with html5 mode as well.