Use common patterns for different states
I want to be able to use two common components across my application in all states, in the main header and sidebar. I read the docs but I must have missed something. How can I reuse header and sidebar in states
$stateProvider
.state('home', {
url: '/leads:id',
views: {
'details': {
templateUrl: '../views/details.html',
controllerProvider: function($stateParams) {
if($stateParams.id) {
return 'CompanyDetails as companydetails';
}else {
return 'NewCompanyDetailsController as companydetails';
}
}
},
'sidebar': {
templateUrl: '../views/sidebar.html'
},
'header': {
templateUrl: '../views/header.html',
controller: 'HeaderCtrl as header'
},
'vehicledetails': {
templateUrl: '../views/vehicledetails.html',
controller: 'VehicleDetailsController as vehicledetails'
},
'comments': {
templateUrl: '../views/comments.html',
controller: 'CommentsController as comments'
},
'saveupdate': {
templateUrl: '../views/saveupdate.html',
controller: 'SaveUpdateDetailsController as saveupdate'
}
}
});
I want to create another state called "data" for example that reuses the header and sidebar. How can I achieve this without having to rewrite all the components?
I did some reading and now I have an updated state provider that displays a common header and sidebar on all routes, but the data inside the actual container is not displayed at all. Here is my updated code
$stateProvider
.state('home', {
abstract: true,
views: {
'header': {
templateUrl: '../views/header.html',
controller: 'HeaderCtrl as header'
},
'sidebar': {
templateUrl: '../views/sidebar.html'
}
},
resolve: {
somedata: function(){return {}}
}
})
.state('home.login', {
url: '/',
views: {
'login@home': {
templateUrl: '../views/login.html'
}
}
})
.state('home.leads', {
url: '/leads:id',
views: {
'details@home': {
templateUrl: '../views/details.html',
controllerProvider: function($stateParams) {
if($stateParams.id) {
return 'CompanyDetails as companydetails';
}else {
return 'NewCompanyDetailsController as companydetails';
}
}
},
'vehicledetails@home': {
templateUrl: '../views/vehicledetails.html',
controller: 'VehicleDetailsController as vehicledetails'
},
'comments@home': {
templateUrl: '../views/comments.html',
controller: 'CommentsController as comments'
},
'saveupdate@home': {
templateUrl: '../views/saveupdate.html',
controller: 'SaveUpdateDetailsController as saveupdate'
}
}
});
and my index.html
<body ng-app="MyApp">
<div id="page-wrapper" ng-class="{'open': toggle}" ng-cloak class="open" ng-controller="SlideCtrl">
<div id="sidebar-wrapper" ui-view="sidebar">
</div>
<div id="content-wrapper">
<div class="page-content">
<!-- Header Bar -->
<div class="row header" ui-view="header">
</div>
<!-- Header Bar -->
<div ui-view="login"></div>
<div ui-view="details" class="panel panel-default col-xs-11" ></div>
<div ui-view="vehicledetails" class="panel panel-default col-xs-11" ></div>
<div ui-view="comments" class="panel panel-default col-xs-11" ></div>
<div ui-view="saveupdate"></div>
</div>
</div>
</div>
<script src="js/main.js"></script>
</body>
source to share
I actually managed to get this working now using this link fooobar.com/questions/264047 / ...
I'll explain my answer as I couldn't figure out how it works before I did it myself. You need this to be present for child states to connect to it. https://github.com/angular-ui/ui-router/wiki/Nested-States-%26-Nested-Views#scope-inheritance-by-view-hierarchy-only
Basically you create a main ng-view inside index.html that serves as a container for your rest of the partial files, then you basically contain all the child ui-views inside another layout that will serve as a parent for all states.
So essentially your structure is like this
<body ng-app="MyApp">
<div id="page-wrapper" ng-class="{'open': toggle}" ng-cloak class="open" ng-controller="SlideCtrl">
<div ng-view>
</div>
</div>
<script src="js/main.js"></script>
and another file with layouts
<div id="sidebar-wrapper" ui-view="sidebar">
</div>
<div id="content-wrapper">
<div class="page-content">
<!-- Header Bar -->
<div class="row header" ui-view="header">
</div>
<!-- Header Bar -->
<div ui-view="login"></div>
<div ui-view="details" class="panel panel-default col-xs-11" ></div>
<div ui-view="vehicledetails" class="panel panel-default col-xs-11" ></div>
<div ui-view="comments" class="panel panel-default col-xs-11" ></div>
<div ui-view="saveupdate"></div>
</div>
</div>
Then you basically follow the pattern here
$stateProvider
.state('home', {
abstract: true,
views: {
'@': {
templateUrl: '../views/layouts.html'
},
'header@home': {
templateUrl: '../views/header.html',
controller: 'HeaderCtrl as header'
},
'sidebar@home': {
templateUrl: '../views/sidebar.html'
}
}
})
.state('home.login', {
url: '/',
views: {
'login@home': {
templateUrl: '../views/login.html'
}
}
})
For all your conditions. This worked for me and I am sure this is the correct way to do it.
source to share
There's a better way:
part of HTML
Index file (index.html):
<html ng-app="app">
<head></head>
<body ui-view></body>
</html>
Base file (layout.html)
<header>
Here the header part
</header>
<aside>
Here the sidebar part
</aside>
<main ui-view>
And here is where the app will be ran when you go to a state like "app.home"
</main>
States:
var states = {
'app': {
templateUrl: 'app/layout.html',
controller: 'LayoutController as layout'
},
'app.home': {
templateUrl: 'app/home.html',
controller: 'HomeController as home'
}
};
angular.forEach(states, function(config, name) {
$stateProvider.state(name, config);
});
source to share