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.
Related
Pretty new to Angular, I am sure I'm missing something obvious here. I am using ui-router.
I want to provide a link to my clients so that they can click the URL link and visit the web app with the appropriate partial. I also want to be able to pass in parameters. Here's how I approached this (kind of hokey). This is in my main controller:
var pNumber = $location.search().number;
if (!(pNumber == null || pNumber == "")){
$state.go('view-ticket');
}
Here is my app.js:
$stateProvider
.state('home', {
url: "/",
templateUrl: 'partials/welcome-screen.html',
controller: 'mainPageController'
})
.state('submit-ticket', {
url: "/submit-ticket",
templateUrl: 'partials/ticket-submit.html',
controller: 'TicketSystemTestCtrl'
})
.state('view-ticket', {
url: "/view",
templateUrl: "partials/ticket-central.html",
controller: 'TicketCentralCtrl'
})
The logic is this: If the URL contains a param 'number' inject ticket-central.html partial.
However, when I run this in the debugger, it seems the first part of the code got executed before it loads the welcome-screen.html partial. How to solve this?
EDIT: I am trying to type this into the URL: http://localhost/techsupport/view and I want it to load the ticket-central.html partial into the main view. However, it won't work.
if i understand correctly all you want to do is to provide a possibility to 'deep-link' to the 'view-ticket' state.
for this search params are not the ideal solution as they are optional, just use path variables:
.state('view-ticket', {
url: '/view/:ticketNumber,
template: 'partials/ticket-central.html',
controler: 'TicketCentralCtrl'
})
also don't use the $location service if you don't really have to, have a look at $stateParams
here is a small plunkr with a welcome and a ticket state
launch the preview in a separate window to see how the url changes - you can also refresh on each page and the correct state will be loaded
https://plnkr.co/edit/r3UcYbfwET0OVwkd77Rv
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
I am not sure what the problem is, im assuming its something with the way my angular routing is? If anyone could help that would be very appreciated.
This is my controller, the console log here actually prints.
app.controller('ClientCtrl',['$http','$scope',
'$stateParams',function($http,$scope, $stateParams){
var clientid = [$stateParams.id];
var client = this;
client.infos = []
$http.get('../client.JSON').success(function(data){
client.infos = data;
console.log(client.infos)
});
}]);
This is my routes, im using ui.router, since im using angular. the client route is the one causing problems.
planoxApp.config(['$stateProvider','$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/templates/index.html',
controller: 'MainCtrl',
})
.state('clients', {
url: '/clients/{id}',
templateUrl: 'clientsmain.html',
controller: 'ClientCtrl'
})
.state('photoplans', {
url: '/photoplans/:id',
templateUrl: 'photoplanmain.html'
});
}])
This is the html file thats causing me problems
<h1>Hi! </h1>
<div class="col-sm-6" ng-repeat="info in client.infos" >
<p>{{info.active}}</p>
</div>
<script> console.log("this sucks") console.log(client.infos)</script>
And this is the console right now
I have tried everything i can think of to get this to work, but nothing works currently. As you can see angular is not throwing errors, but nothing is console logging from this page nor is the ng-repeat working. Any help is greatly appreciated, thanks in advance.
You have already printed a result from the angular controller in console its there in screen shot.
Seems like you should us controllerAs alias there for controller, you could declare alias inside your state itself like by doing controller: 'ClientCtrl as client'
Markup
<h1>Hi! </h1>
<div class="col-sm-6" ng-repeat="info in client.infos" >
<p>{{info.active}}</p>
</div>
State
.state('clients', {
url: '/clients/{id}',
templateUrl: 'clientsmain.html',
controller: 'ClientCtrl as client'
})
Update
You can not load script from the partials, they will never get readed when they are loaded through the partial html. Though using console.log(client.infos) never make sense how can you think of angular context will available for the global script.
If you want it something like this then you could take a look at this thread, but my personal advice is you shouldn't go for this.
I am trying to enter a ui-router parent or child state simply by navigating to its associated URL. I know that ui-sref is a proven, simple way to enter into a state via an a link, but just typing the URL of a state into a browser seems to always redirect me to my $urlRouterProvider.otherwise() statement.
For example, I would like to be able to navigate into the page state, via going to example.com/#/page in the browser. Instead, I am redirected to the otherwise.
JS
angular.module('app', [ 'ui.router', 'subapp']);
angular.module('app').config(function($urlRouterProvider, $locationProvider) {
}).controller('appCtrl', function(){});
angular.module('subapp', ['ui.router']);
angular.module('subapp').config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.when('#/page/nothing', '/');
$stateProvider
.state('page', {
url: '#/page',
templateUrl: 'page.tpl.html'
})
.state('page.edit', {
url: '/:myparameter',
templateUrl: 'page-edit.tpl.html'
});
$urlRouterProvider.otherwise('/hello');
});
Index.html
<body ng-controller="appCtrl">
This is the index.html file<br>
Go to page state<br>
Go to page child state with a parameter
<ui-view></ui-view>
PLNKR: http://plnkr.co/edit/HQziTB2CyJrCvbgzzuJm?p=preview
ote I have a subapp service which is injected into the main app—but I don't think that would make a difference, as page state should still be a 'top-level' state injected into the index.html <ui-view>
How can I make it so that I can navigate to a URL (even one with a parameter) directly? The documentation says its possible, but I can't seem to get it to work.
I would say, that you are almost there. There is an updated plunker. But while your links could (should) be with # (we are not using html5Mode)
<a href="#/page">
<a href="#/page/myparameter">
<a href="#/page/11">
The state definition should not contain that sign:
.state('page', {
// instead of this
// url: '#/page',
// we need this
url: '/page',
...
.state('page.edit', {
// instead of this
// url: '#/:page',
// we need this
url: '/:page',
And then also these will work:
<a ui-sref="page">
<a ui-sref="page.edit({page:123})">
<a ui-sref="page.edit({page:444})">
Check it here
Your parameter URL is wrong, you cannot map URL with a fixed name and other url with a parameter cause will cause a crazy rewrite thinking this is a variable
$stateProvider
.state('page', {
url: '#/page',
templateUrl: 'page.tpl.html'
}
).state('page.edit', {
url: '/:myparameter',
templateUrl: 'page-edit.tpl.html'
});
Use URL by this way:
$stateProvider
.state('page', {
url: '/page',
templateUrl: 'page.tpl.html'
}
).state('page.edit', {
url: '/page/:myparameter',
templateUrl: 'page-edit.tpl.html'
});
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.