Angular.js: Layouts and Sections
I've been building out the new UI for Octopus 2.0 in Angular.js, which has been a fun process and something I hope to blog more about later.
Coming from an ASP.NET MVC background, one of the concepts I found myself missing was that of "sections". A solution I came up with was to use two custom directives:
octo-placeholder
designates an area on the parent layout where content will be placedocto-section
designates content that will be added to the parent layout
My layout page looks like this (simplified):
<... snip ...>
<body>
<div class='top'>
<div class='tools' octo-placeholder='tools'></div>
<div class='breadcrumbs' octo-placeholder='breadcrumbs'></div>
</div>
<ng-view></ng-view>
</body>
My view looks like this:
<script octo-section="breadcrumbs" type="text/ng-template" >
<p>This is the breadcrumbs area {{ someVariable }}</p>
</script>
<script octo-section="tools" type="text/ng-template" >
<a ng-show="loaded">Hello</a>
</script>
<p>This is the main content</p>
The directives that make this all work are:
.directive("octoPlaceholder", function(octoUtil, $compile, $route, $rootScope) {
return {
restrict: 'AC',
link: function(scope, element, attr) {
// Store the placeholder element for later use
$rootScope["placeholder_" + attr.octoPlaceholder] = element[0];
// Clear the placeholder when navigating
$rootScope.$on('$routeChangeSuccess', function(e, a, b) {
element.html('');
});
}
};
})
.directive("octoSection", function(octoUtil, $compile, $route, $rootScope) {
return {
restrict: 'AC',
link: function(scope, element, attr) {
// Locate the placeholder element
var targetElement = $rootScope["placeholder_" + attr.octoSection];
// Compile the template and bind it to the current scope, and inject it into the placeholder
$(targetElement).html($compile(element.html())(scope));
}
};
})
Unlike solutions that use ng-include
, the directives use the current view's scope rather than creating a new scope. This means that you can use bindings within the sections without a problem.
Hopefully this helps someone else!