Angularjs ui-router not reaching child controller - javascript

I've got a config function:
function config($stateProvider,$locationProvider) {
$locationProvider.html5Mode(true);
$stateProvider
.state('projectsWs.tasks', {
url: "/tasks",
views: {
"mainView": {
templateUrl: "/app/projects/templates/index.php"
},
"innerView": {
templateUrl: "/app/projects/templates/tasks.php",
controller: tasksCtrl,
controllerAs:'tasks'
}
}
})
.state('projectsWs.tasks.detail', {
url: "/:taskId",
views: {
"mainView#": {
templateUrl: "/app/projects/templates/index.php"
},
"innerView#mainView": {
templateUrl: "/app/projects/templates/tasks.php",
controller: function($stateParams) {
console.log('innerViewCtrl', $stateParams);
}
}
}
});}
InnerView is inside mainView.
When I've got url like /projects-ws/tasks, tasksCtrl function works as expected. But when I've got url with an id, i.e. /projects-ws/tasks/32, I don't see any output, but I expect innerViewCtrl output, that's the problem I got. I think I've got a problem with absolute/relative views, but I've allready tried all combinations and it still don't work.
UPDATE:
So now I've got following state:
state('projectsWs.tasks.detail', {
url: "/:taskId",
views: {
"mainView#": {
templateUrl: "/app/projects/templates/index.php",
controller: function($stateParams) {
console.log('mainViewctrl', $stateParams);
}
},
"innerView": {
templateUrl: "/app/projects/templates/tasks.php",
controller: function($stateParams) {
console.log('innerViewctrl', $stateParams);
}
}
}
})
as Radim Köhler said. It outputs mainViewctrl Object {taskId: "32"}, but how can I reach $stateParams.taskId from innerView now?

Absolute naming with UI-Router works a bit differntly then you've used it
.state('projectsWs.tasks.detail', {
url: "/:taskId",
views: {
"mainView#": {
templateUrl: "/app/projects/templates/index.php"
},
// this won't work, because the part after #
// must be state name
"innerView#mainView": {
// so we would need this to target root, index.html
"innerView#": {
// or this to target nested view inside of a parent
"innerView": {
// which is the same as this
"innerView#projectsWs.tasks": {
Check the:
View Names - Relative vs. Absolute Names
small cite:
Behind the scenes, every view gets assigned an absolute name that follows a scheme of viewname#statename, where viewname is the name used in the view directive and state name is the state's absolute name, e.g. contact.item. You can also choose to write your view names in the absolute syntax.
I created a working example here, and the states are like this
$stateProvider
.state('projectsWs', {
template: '<div ui-view="mainView" ></div>' +
'<div ui-view="innerView" ></div>',
})
$stateProvider
.state('projectsWs.tasks', {
url: "/tasks",
views: {
"mainView": {
//templateUrl: "/app/projects/templates/index.php"
template: "<div>main view tasks </div>",
},
"innerView": {
//templateUrl: "/app/projects/templates/tasks.php",
template: "<div>inner view tasks </div>",
}
}
})
.state('projectsWs.tasks.detail', {
url: "/:taskId",
views: {
"mainView#projectsWs": {
//templateUrl: "/app/projects/templates/index.php"
template: "<div>main view task {{$stateParams | json }} </div>",
},
"innerView#projectsWs": {
//templateUrl: "/app/projects/templates/tasks.php",
template: "<div>inner view task {{$stateParams | json }} </div>",
}
}
});
What we can see is, that the grand parent projectsWs is injecting into index.html (root) <div ui-view=""> some template, with two named anchors:
template: '<div ui-view="mainView" ></div>' +
'<div ui-view="innerView" ></div>',
this are then used in list and detail states, with relative resp absolute names
Check it here in action

Related

angular-ui/ui-router parent state with a default view

I'm trying to define states in a 3 columns layout with the left column having the same content. But at this time, I had to repeat the templateUrl for all direct nested states.
.state('workspace', {
url: '/',
templateUrl: 'app/workspace/workspace.view.html'
})
.state('workspace.images', {
url: 'images',
views: {
'sidebar': {
templateUrl: 'app/workspace/sidebar.view.html',
controller : 'Workspace.SidebarController as vm'
},
'content': {
templateUrl: 'app/workspace/imageslist.view.html',
controller : 'Workspace.ImagesListController as vm'
}
}
})
.state('workspace.images.edit', {
url: '/:key',
templateUrl: 'app/workspace/editor.view.html',
controller : 'Workspace.EditorController as vm'
})
.state('workspace.documents', {
url: 'documents',
views: {
'sidebar': {
templateUrl: 'app/workspace/sidebar.view.html',
controller : 'Workspace.SidebarController as vm'
},
'content': {
templateUrl: 'app/workspace/documentslist.view.html',
controller : 'Workspace.DocumentsListController as vm'
}
}
});
As you can see, I have to repeat the "sidebar" template each time. I would like to be able to configure it form the abstract workspace state.
workspace.view.html contains the "sidebar" and "content" views :
<div class="sidebar" ui-view="sidebar">
<!-- view = sidebar -->
</div>
<div class="content" style="height: 100%" ui-view="content">
<!-- view = content-->
</div>
I think I should have a views object into the "workspace" state to define the "sidebar" templates and controllers and leave the "content" empty.
And have tried with and without named views but without success. When I do that, the sidebar template is never displayed but seems to be loaded (a wrong name cause a 404 in my console).
This will inject sidebar into parent... and child can use it or even change it:
.state('workspace', {
url: '/',
views: {
'': { templateUrl: 'app/workspace/workspace.view.html' }
'sidebar#workspace': {
templateUrl: 'app/workspace/sidebar.view.html',
controller : 'Workspace.SidebarController as vm'
},
}
})
.state('workspace.images', {
url: 'images',
views: {
'content': {
templateUrl: 'app/workspace/imageslist.view.html',
controller : 'Workspace.ImagesListController as vm'
}
}
})
...
We used views : {} even on parent state. The default unnamed is the original workspace.view.html
We also added named view 'sidebar#workspace' - the absolute name here means, that the name is 'sidebar' and its target is searched inside of the 'workspace' state templates

Changing only one of multiple named, nested routes

I have a template with multiple named, nested views:
template 1:
<body>
<div ui-view></div>
</body>
template 2:
<header></header>
<div ui-view="left"></div>
<div ui-view="canvas"></div>
<div ui-view="right"></div>
and I have the following config setup:
.state("metricDashboard", {
url: "/metric-dashboard",
css: { href: "core/metric-dashboard/style.css" },
views: {
"": {
templateUrl: "core/metric-dashboard/view.html",
controller: 'MetricDashboard',
},
"left#metricDashboard": {
templateUrl: "core/metric-dashboard/partials/left.html",
controller: "MetricDashboardLeft",
},
"canvas#metricDashboard": {
templateUrl: "core/metric-dashboard/partials/canvas.html",
controller: "MetricDashboardCanvas"
},
"right#metricDashboard": {
templateUrl: "core/metric-dashboard/partials/right.html",
controller: "MetricDashboardRight"
}
}
})
How would I go about changing an individual route? For example, If I wanted to change "left#metricDashboard", but leave the "canvas" and "right" routes alone. I cannot seem to find a syntax without creating a new state and explicitly declaring all the routes over again.
Ok I'm guessing you want to create another state that will change only one of the views not all of them.
Let's call it left and make it a child of metricsDashboard
.state("metricDashboard", {
url: "/metric-dashboard",
css: { href: "core/metric-dashboard/style.css" },
views: {
"": {
templateUrl: "core/metric-dashboard/view.html",
controller: 'MetricDashboard',
},
"left#metricDashboard": {
templateUrl: "core/metric-dashboard/partials/left.html",
controller: "MetricDashboardLeft",
},
"canvas#metricDashboard": {
templateUrl: "core/metric-dashboard/partials/canvas.html",
controller: "MetricDashboardCanvas"
},
"right#metricDashboard": {
templateUrl: "core/metric-dashboard/partials/right.html",
controller: "MetricDashboardRight"
}
}
})
.state("metricDashboard.left", {
url: "left",
views: {
"left#metricDashboard" : {
templateUrl: "some.html",
controller: "AwesomeCtl",
controllerAs: "awe"
}
}
})
Now when you enter that state only the left view will change the others will remain as defined in the parent state metricDashboard.

Accessing child state parameters in parent in Angular UI-Router

I have the following state configuration. How can I get id parameters in index state # view so that it could be accessible by both, left and detail views controllers? Now if I try to access it via $state.params.id it is undefined, but if I console.log($state) I can see the parameter in my console. I only need the parameter if available on first load of left view.
$stateProvider
.state('index', {
url: '/',
views: {
'#' : {
template: '/**/'
resolve: {
params: function ($state) {
return $state.params.id;
}
}
},
'left#index' : {
template: '/**/',
controller: 'AppController',
controllerAs: 'app'
},
'main#index' : {
template: '/**/'
}
})
.state('index.detail', {
url: '/:id',
views: {
'detail#index' : {
template: '/**/',
controller: 'DetailController',
controllerAs: 'detail',
}
}
});

Error: Could not resolve 'storysolo' from state 'index'

I have my index.php page with a ui-sref link as follows
<a ui-sref="storysolo({ storyId: headline.nid })">
I have my main js file loading the angular code as follows
var rebelFleet = angular.module("CougsApp", ["ui.router","ngAnimate", "ui.bootstrap", "ngSanitize", "slick","CougsApp.headlines","CougsApp.story","CougsApp.recentstories" ]);
rebelFleet.config(function($stateProvider) {
// For any unmatched url, redirect to /state1
$stateProvider
.state('index', {
url: "",
views: {
"navViewPort": { templateUrl: '/components/nav/nav.html'
},
"contentViewPort": {
templateUrl: '/components/headlines/headlines.html',
controller: "headlinesCtrl"
},
"eventsViewPort": { templateUrl: '/components/scroller/scroller.html' },
"bottomContentViewPort": { templateUrl: '/components/recentstories/recentstories.html',
controller: "recentstoriesCtrl"
},
"rightsideViewPort": { templateUrl: '/components/social/social.html' },
"footerViewPort": { templateUrl: '/components/footer/footer.html' }
}
})
Then I have my story.js file trying to load with it's own routing. as follows
var ywing = angular.module('CougsApp.story', ["ui.router"]);
ywing.config(function($stateProvider, $urlRouterProvider) {
$stateProvider.state('storySolo', {
url: '/story/:storyId',
views: {
"navViewPort": { templateUrl: '/components/nav/nav.html'
},
"contentViewPort": {
templateUrl: '/components/story/story.html',
controller: "storyCtrl"
},
"footerViewPort": { templateUrl: '/components/footer/footer.html' }
}
})
});
So when I load my page and click on the ui-sref link I get this error
Could not resolve 'storysolo' from state 'index'
my order of files being loaded is as follows
angular.js,
angular-sanitize.js,
angular-ui-router.js,
rebelFleet.js, (the main js file)
story.js
I'm guessing I'm doing something wrong with the way the routes are being loaded and UI-Router hates it. Any help would be much appreciated.
There is a working example
Believe or not, it is very simple - it is about case sensitivity. State names must fit on the 1) definition as well on the 2) call side
// small solo
<a ui-sref="storysolo({ storyId: headline.nid })">
// capitalized Solo
$stateProvider.state('storySolo', {...
so just use one or the other, e.g.:
// not small solo
<a ui-sref="storySolo({ storyId: headline.nid })">
// the same name here
$stateProvider.state('storySolo', {...
Check the example here

Angular routes not refreshing the view

I try to create an app with angular, and somehow the child state in not loading.
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state('home', {
url : "/",
templateUrl: "/admin/home/"
})
.state('users', {
url : "/users/",
templateUrl: "/admin/users",
controller : function ($stateParams) {
console.log($stateParams);
console.log("users");
}
})
.state('users.new', {
url : "^/users/user/",
templateUrl: "/admin/users/new",
controller : function () {
console.log("users.new");
}
})
.state('users.user', {
url : "^/users/user/:uuid",
templateUrl: function ($stateParams) {
console.log($stateParams);
return "/admin/users/" + $stateParams.uuid
},
controller : function () {
console.log("users.user");
}
});
When I visiting the page
/users/user/55d8b1c706387b11480d60c1
I see the request to load the page, but only the "users" controller got executed.
This problem appears only with child states, switching between parent state working without problems.
I Using the latest versions of angular and ui-routes.
any ideas?
Please read this DOC
You mistake is in hierarchy. Child states use parent template as root and try find nested <ui-view>
You may add abstract state user without url, with empty template <ui-view></ui-view>, for nested viws. Then rename user, to E.G. user.index, it works for me
1st (It may works)
$stateProvider
.state('home', {
url : "/",
templateUrl: "/admin/home/"
})
.state('users', {
template: "<ui-view></ui-view>",
})
.state('users.index', {
url : "/users/",
templateUrl: "/admin/users",
controller : function ($stateParams) {
console.log($stateParams);
console.log("users");
}
})
.state('users.new', {
url : "^/users/user/",
templateUrl: "/admin/users/new",
controller : function () {
console.log("users.new");
}
})
.state('users.user', {
url : "^/users/user/:uuid",
templateUrl: function ($stateParams) {
console.log($stateParams);
return "/admin/users/" + $stateParams.uuid
},
controller : function () {
console.log("users.user");
}
});
2nd way is USE absulutly named views E.G.
views: {
"": { templateUrl: 'pages/menu.html' }, // relative noName view
"header": { templateUrl: "pages/header.html"}, //relative named view
"content#": { // Absolute name
template: "<ui-view></ui-view>",
controller: 'AuthController'}
}

Categories