Angular ui-router: 1 url trigger both parent and child state - javascript

When I go to the url /blog/post/edit, 2 xhr requests trigger, as you can see in the image below.
This is how I have defined the routes:
$stateProvider
.state('blog', {
url: '/blog',
templateUrl: '/blog'
})
.state('blog.post', {
url: '/post',
template: '<ui-view></ui-view>',
abstract: true
})
.state('blog.post.edit', {
url: '/edit',
templateUrl: '/blog/post/edit'
});
Can anyone help me figuring out why this is happening?

As quickly discussed in comments, the nature of the ui-router is to work this way. To show nested states with their parent states
The best way how to think about it is like a collapsed TreeView:
if we want to see a leaf (or any not root node) we have to see/load its parent, grand-parent ... and the root as well.
but once we want to see a sibling, we do not have to reload all the parent-to-root structure... is is already in play
And that's how the ui-router was basically designed.

Related

Prevent state reloading when changing states ui-router

I understand this has been asked and answered in multiple posts but I have attempted the solutions and still can't quite get there yet.
I have a few components that I'm routing between with ui-router and one is a contact form which, if a user enters data to and moves to another route then back to the contact form the state is reloaded and the form contents gone.
I saw another way of doing this by having a parent state and child states but couldn't recreate this in my code.
Maybe there's a simpler solution by using ui-router-extras with the sticky option although I attempted this and could't get it working either. I'll post the code as it works now.
(function () {
angular.module('personalPortfolio')
.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('about', {
sticky: true,
url: '/about',
template: '<pg-about></pg-about>'
})
.state('development', {
sticky: true,
url: '/work',
template: '<pg-dev></pg-dev>'
})
.state('contact', {
sticky: true,
url: '/contact',
template: '<pg-contact></pg-contact>'
});
$urlRouterProvider.otherwise('/about');
}]);
})();
You can create a service when You will store unsaved form data.

angularJs stateprovider sub state doesn't load controller and template

I created this small app where I have following states:
restricted.route.js
$stateProvider.state('restricted', {
url: '/restricted',
templateUrl: 'app/restricted/restricted.html',
abstract: true
});
pages.route.js
$stateProvider.state('restricted.pages', {
url: '/pages',
templateUrl: 'app/restricted/pages/pages.html',
controller: 'pagesController',
controllerAs: 'vmPages'
});
detail.route.js
$stateProvider.state('restricted.pages.detail', {
url: '/:id',
controller: 'pageDetailController',
controllerAs: 'vmDetail',
templateUrl: 'app/restricted/pages/detail/detail.html'
});
app.run.js
$urlRouterProvider.otherwise('/restricted/dashboard');
When I load the URL #/restricted/pages everything works fine. Controller is loaded and view is shown.
When I load the URL #/restricted/pages/1 the controller and view from the state 'restricted.pages' is loaded and executed.
The state is clearly recognized, because the $urlRouterProvider.otherwise is not executed.
Does anyone have an idea what I'm doing wrong here?
Thanks!
Is it intentional to have the details as a substate of the pages (list?) state? If so, you need to place an <div ui-view></div> into the template named app/restricted/pages/pages.html.
If that was not your intention, I recommend to rename the detail state to something like restricted.pages_detail as every dot introduces a nested level in the state definitions.
I think your issue lies in the HTML, the nested state should be loaded in a ui-view tag on the parent element.

Angular UI-Router - parameters in child and parent state returning wrong template

I have an application based on Angular with the UI-Router. I'm trying to get the following URL structure
/base/category
/base/category/id
while serving different templates for each route.
I've been searching around a lot but couldn't find anything that helps me.
My code:
$stateProvider
.state('app', {
url: '',
templateUrl: 'views/app.html',
abstract: true
})
.state('base', {
url: '/base',
template: '<div ui-view></div>',
abstract: true,
parent: 'app'
})
.state('base.cat', {
url: '/:catId',
templateUrl: 'views/cat_view.html'
})
.state('base.cat.id', {
url: '/:id',
templateUrl: 'views/id_view.html'
});
Accessing /base/category returns the correct template, but /base/category/id also returns the category template (I want it to return id_view.html). I might want to add more dynamic parameters later on so I want a clean solution for this.
This is my workaround for now:
.state('base.id', {
url: '/:catId/:id',
templateUrl: 'views/id_view.html'
});
It works but the UI-Router doesn't trigger the active classes in my menu.
Thanks for taking time to read this, if you just point me in the right direction that helps me a lot!
There is a working example with the code above
Your concept is ok, just be sure, that parent has place for its child:
<div ui-view></div>
So, in our case, I added the above line into views/cat_view.html. That is the parent state view of the state 'base.cat.id'. These links are now working:
<a href="#/base/category">
<a href="#/base/category/1">
<a href="#/base/category/22">
Check it in action here

Can't navigate to ui-router state with URL

I'm working on a simple angular application using ui-router. I have a couple states for selecting and then editing information about a publisher. The relevant config:
.state('select-publisher', {
url: '/select-publisher',
templateUrl: '/Content/superadmin/src/templates/publishers/publishers.html'
})
.state('publisher', {
abstract: true,
url: 'publisher/{id:int}',
templateUrl: '/Content/superadmin/src/templates/publishers/publisher.html'
})
.state('publisher.details', {
url: '/details',
templateUrl: '/Content/superadmin/src/templates/publishers/details.html'
})
.state('publisher.ad-tags', {
url: '/ad-tags',
templateUrl: '/Content/superadmin/src/templates/publishers/ad-tags.html'
})
.state('publisher.native-ads', {
url: '/native-ads',
templateUrl: '/Content/superadmin/src/templates/publishers/native-ads.html'
})
Inside the select-publisher state I have a big list of available publishers. Each one of them is bound to an ng-click event that triggers the following function in my controller:
$scope.selectPublisher = function(publisher) {
publisherService.setSelectedPublisher(publisher);
$state.go('publisher.details', {id: publisher.Id});
};
This works just fine and takes me to the publisher.details state and renders the proper view. At this point the URL in my browser points to localhost:1337/superadmin#/publisher/39/details where 39 is the ID of the publisher that I selected.
The problem is, if I refresh this page or attempt to navigate directly to it by pasting the URL into the browser from another area of the application, I am ALWAYS taken back to the select-publisher state. I would like to be able to configure my states such that I am able to navigate to the details state (or any other state) based on URL.
Worth noting is that I do have a catch all route defined after all of my states:
$urlRouterProvider.otherwise('/select-publisher');
I'm assuming that for some reason this is being triggered but I can't reason as to why navigation works in my app using either $state.go as I have indicated in my controller as well as using ui-sref directive in my HTML templates but not through navigating directly to the URL.
Maybe it's because of missing slash url: /publisher/{id:int}

Angular UI-router default state on same URL

This is going to be difficult to explain but I'll try.
I am using UI-router in an angular app and would like t use the following URLS:
/contacts
/contacts/{id}
When you visit the /contacts page it will get a list of contacts from the server and display them. When you go to /contacts/1 it will get the contact 1 record from the server and show it.
My code currently looks like this:
.state('contacts', {
url: "/contacts",
templateUrl: "templates/contacts.tpl.html",
controller: "ContactsCtrl"
})
.state('contacts.contact', {
url: "/{contactID}",
templateUrl: "templates/contact.tpl.html",
controller: "ContactCtrl"
})
So far so good. but when you go to the second URL the parent is also activated so it's going to the server to get the list of contacts, even though they're not displayed, which is a waste.
I could set /contacts to "abstract:true" and use /contacts/list as the first URL, but that's not the URL I want to use and I do need to set a controller on the parent because I do have some logic I want to put in the parent (creating the navigation for that section).
Ideally, when the user hits /contacts I'd like the parent state to activate (to create the navigation) and run a default child state to list the contacts without redirecting to another URL. If the user goes to /contacts/8 then It would still activate the parent state but not the default state so it never goes to the server to get the contacts.
I hope that makes sense. I've not been able to create a plunkr, but the Angular UI guys kindly created one which shows the imperfect solution above.
http://plnkr.co/edit/gmtcE2?p=preview
I could set /contacts to "abstract:true"
That would be one part of the correct approach. A parent state should not load data that doesn't apply to a child, but your state tree doesn't have to reflect your URL structure exactly. For example:
.state('contacts', {
abstract: true,
url: "/contacts",
/* Various other settings common to both child states */
})
.state('contacts.list', {
url: "", // Note the empty URL
templateUrl: "templates/contacts.tpl.html",
controller: "ContactsCtrl"
})
.state('contacts.item', {
url: "/{id}",
templateUrl: "templates/contact.tpl.html",
controller: "ContactCtrl"
})

Categories

Resources