It seems that having a controller in an abstract named view will not fire that controller when a child view also implements a controller, only the child controller fires. My setup is as follows:
$stateProvider
.state('app', {
abstract: true,
views : {
header: {
template: "<p>My header</p>"
},
section: {
template: "<ui-view />",
controller: function () {
alert('loaded main control');
}
}
}
})
.state('app.home', {
url: '',
views: {
'section#': {
template: "<p> My initial content here </p>",
controller: function () {
alert("loaded home control");
}
}
}
})
http://plnkr.co/edit/WjUYwEfrNbZrdpUQAole?p=preview
In my mind the above demo should trigger both alerts, why is this not happening?
In the app.home you are using the section# as the view name, which is an absolute match, and then is conflicting with the section view defined in the abstract app state.
In fact, the first section view appears to be useless. You can try the following snippet.
$stateProvider
.state('app', {
abstract: true,
views : {
header: {
template: "<p>My header</p>",
controller: function () {
alert("loaded main control");
}
}
}
})
.state('app.home', {
url: '',
views: {
'section#': {
template: "<p> My initial content here </p>",
controller: function () {
alert("loaded home control");
}
}
}
})
More details available in the Multiple Named Views section of the ui-router guide.
Related
I'd like to load a template using Angular controller. I have created everything needed:
routes.config.js
index.component.js
index.config ( here is the config of the parent controller )
html
js controller
connected with php controller
I already created templates and controllers exactly the same way and I have no idea what am I doing wrong. It's interesting that when I open elements tab in the browser I can see the <statistic-test></statistic-test> tags, and url also change. If I change <statistic-test></statistic-test> to another tag which is already used in another controller then it loads.
test-question.component.js
class TestQuestionController{
constructor($scope, $state,$stateParams, $compile, DTOptionsBuilder, DTColumnBuilder, API){
'ngInject';
this.API = API
this.$state = $state
if ($stateParams.mode) {
this.mode=$stateParams.mode
}
let Statics = API.service('show', API.all('statisticQuestion'))
this.userlistaction = "app.statisticanswer.userlist"
}
$onInit(){}
}
export const TestQuestionComponent = {
templateUrl: './views/app/components/statistic-question-userlist/test-question.component.html',
controller: TestQuestionController,
controllerAs: 'vm',
bindings: {}
}
I also have an html named test-question.component.html
routes.config.statistic.question.js
export function RoutesConfigStatisticQuestion ($stateProvider) {
'ngInject'
$stateProvider
.state('app.statisticquestion', {
url: '/statistic-question',
data: {
auth: true
},
views: {
'main#app': {
template: '<statistic-question></statistic-question>'
}
},
ncyBreadcrumb: {
label: 'Kérdések statisztika',
}
})
.state('app.statisticquestion.test', {
url: '/statistic-test/',
data: {
auth: true
},
views: {
'main#app': {
template: '<statistic-test></statistic-test>'
}
},
params: {
contentsId : null,
alerts: null
},
ncyBreadcrumb: {
label: 'Címke szerkesztése',
parent: 'app.statisticquestion'
}
})
If you have ANY idea how to solve this please share it with me.
https://plnkr.co/edit/VV13ty8XaQ20tdqibmFy?p=preview
Expected
After login the dashboard state renders dashboard.html, and all components and ui-views should render: tickers, tags, social(named ui-view) and feed.
Results
After login the dashboard state renders dashboard.html however only the components tickers,tags and feed show up, but not the social (named-ui-view)
I feel that my problem lies somewhere around where I transition from the login state to the dashboard state. Once you hit the dashboard state, it serves up the default template which is the component element tag: <dash-module></dash-module>. This will then render the dash.component template: dashboard.html and controller. However I've lost access to the social view in the dashboard state object.
dashboard.html
<div class="jumbotron text-center">
<h1>The Dashboard</h1>
</div>
<div class="row">
<tickers-module></tickers-module>
<tags-module></tags-module>
// Expecting the social-module-template.html to show below:
<div ui-view="social"></div>
<feed-module></feed-module>
</div>
The routerApp module with the dashboard component full code in Plnkr
// RouterApp module
////////////////////////////////////////////////////////////////////////////////
var routerApp = angular.module('routerApp', ['ui.router', 'tickers', 'tags', 'feed']);
routerApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/login');
const login = {
name: 'login',
url: '/login',
templateUrl: 'login.html',
bindToController: true,
controllerAs: 'l',
controller: function($state) {
this.login = function() {
$state.go('dashboard', {});
}
}
}
const dashboard = {
name: 'dashboard',
url: '/dashboard',
params: {
ticker: {},
tags: {}
},
template: '<dash-module></dash-module>',
views: {
'' : {
templateUrl: 'dashboard.html',
},
'social' : {
templateUrl: 'social-module-template.html',
controller: function($state) {
console.log('Social init', $state.params);
}
}
}
}
$stateProvider
.state(login)
.state(dashboard);
})
tags.component('dashModule', {
templateUrl: 'dashboard.html',
controller: function($scope, $state) {
console.log('dashModule loaded!');
}
})
This is the part that should render the social html content in the <div ui-view="social"></div>
views: {
'' : {
templateUrl: 'dashboard.html',
},
'social' : {
templateUrl: 'social-module-template.html',
controller: function($state) {
console.log('Social init', $state.params);
}
}
}
I made changes to your plunker here You were missing # here.
const dashboard = {
name: 'dashboard',
url: '/dashboard',
params: {
ticker: {},
tags: {}
},
template: '<dash-module></dash-module>',
views: {
'' : {
templateUrl: 'dashboard.html',
},
'social#dashboard' : {
templateUrl: 'social-module-template.html',
controller: function($state) {
console.log('Social init', $state.params);
}
}
}
}
In order for these components to appear under the home state, we must define them using absolute naming. Specifically, we must use the # syntax to tell AngularJS that these components of our application should be mapped to a specific state. This follows the viewName#stateName syntax and tells our application to utilize named views from an absolute, or specific state. You can read more about relative vs. absolute names here.
See this for more information.
The problem you have is named view has to render in same state i.e Dashboard.
Change the following and it should work.
social#dashboard
Check this Plunkr
Named Views UI router
i have an angularjs app with components and i want to add a view as child of another view using ui.router. i honestly dont think that ui.router fully support component, this may happen in upcomping 1.0 version. But in the meanwhile is anything that i can do to use display view dynamically?
this is my $stateProvider (i've done my attempts)
$stateProvider
.state('home', {
url :'/home',
template :'<home></home>'
})
.state('projects', {
url:'/projects',
template: "<project-list></project-list>"
})
.state('projectDetails',{
url:'/:projectId',
template : '<project-detail projectDetails="projectDetails"></project-detail>'
, views :{
'chat':{
template : '<chat></chat>'
}
}
});
$urlRouterProvider.otherwise('home');
i have created a component in this way:
(function() {
'use strict';
function ChatController($scope, $element, $attrs, $firebaseArray) {
var ctrl = this;
console.log("it works");
}
angular.module('myapp').component('chat', {
templateUrl: '/app/component/project/chat.html',
controller: ChatController
});
})(window.angular);
and then i've added the view in projectDetails
<div ui-view="chat"></div>
My understanding of your requirement is that you have a component called 'Chat' which you want to load in the state 'project-details' as a nested/child view.
As you have already observed ui-router does not support this.
But this can be achieved by making your 'project-details' as a parent state and load other components included as a child state.
Plunker Demo
angular.module('app', [
'ui.router'
]).config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider.state('home', {
template: '<home></home>'
}).state('home.parts', {
url: '/',
views: {
'about-view#home': {
template: "<about></about>"
},
'chat-view#home': {
template: "<chat></chat>"
}
}
});
}).component('app', {
templateUrl: 'app.html'
}).component('home', {
templateUrl: 'home.html',
controller: homeController,
controllerAs: 'vm'
}).component('about', {
templateUrl: 'about.html',
controller: aboutController,
controllerAs: 'vm'
}).component('chat', {
templateUrl: 'chat.html',
controller: chatController,
controllerAs: 'vm'
});
function chatController() {
this.name = "chat";
}
function aboutController() {
this.name = "about";
}
function homeController() {
this.name = "home";
}
Hope this is what you wanted.Please do not add url to the parent state.Consider making it a abstract state.
I have an app with multiple states that each have nested views. The one state has a conditional templateUrl, and based on a $state.param will show specific HTML/JS. I want to set a query on the URL of the state, so that I know which list item is being looked at when I click it. I cannot figure out how to set a url query and transition to the desired state's view.
My states:
.state('index', {
url: '/',
views: {
'#' : {
templateUrl: 'views/layout.html'
},
'top#index' : {
templateUrl: 'views/top.html',
controller: function($scope, $state) {
$scope.logOut = function() {
$state.go('login');
};
}
},
'left#index' : { templateUrl: 'views/left.html' },
'main#index' : { templateUrl: 'views/main.html' }
}
})
.state('index.list', {
url: 'list?item',
templateUrl: 'views/lists/list.html',
controller: 'ListCtrl'
})
.state('index.list.details', {
url: '/',
params: {
detail: 'overview'
},
controller: ctrl,
views: {
'details#index' : {
templateUrl: function($stateParams) {
if($stateParams.detail === 'status' ) {
ctrl = 'StatusCtrl';
return 'views/details/status.html';
} else if ($stateParams.detail === 'overview') {
ctrl = 'OverviewCtrl';
return 'views/details/overview.html';
}
}
}
},
})
In my controller for the index.list, this is where I have the list and click and populate the details view.
HTML & Js:
<div class="channel" ng-repeat="item in items" ng-click="viewListDetails(item)">
$scope.viewListDetails = function(item) {
$location.search('item', item.id);
$state.go('index.list.details', {detail: 'status'}, {reload: true})
};
My JS above runs the through the function however it does nothing! It will not set the query or transition to the desired view for that sate.
Any help is appreciated!
index.deviceList.detail is not a defined state. You probably intended to write index.list.details.
I want to give 2 parts of my UI the same controller but still let them have each of their own unique controllers.
$stateProvider
.state('standard.page', {
url: '/:page',
resolve: {
page: function($stateParams) {
...
},
},
views: {
'content': {
templateUrl: '/tmpl/page',
controller: 'controllercontent'
},
'sideMenu': {
templateUrl: '/tmpl/menu',
controller: 'controllermenu',
}
}
})
So I want both content and sideMenu to share a controller. If I add a controller above the views then it requires a new template, I want to use the standard template instead of making a unique template for this state. Any ideas how I can get 3 controllers going in this example? Thanks.
I battled with this at some point in time, and I believe I made a template file that isn't directly accessible (via abstract: true). Here's an example...
.state('standard', {
url: '/standard',
abstract: true,
templateUrl: '/tmpl/standard.html',
controller: 'SharedController'
},
})
.state('standard.page', {
url: '/:page',
resolve: {
page: function($stateParams) {
...
},
},
views: {
'content': {
templateUrl: '/tmpl/page',
controller: 'controllercontent'
},
'sideMenu': {
templateUrl: '/tmpl/menu',
controller: 'controllermenu',
}
}
});
In your tmpl/standard.html file, make sure this exists somewhere within the file:
<div ui-view="sideMenu">
<div ui-view="content">
Hope this points you in the right direction.