Standalone Router

by mnk

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.14/angular-ui-router.js"></script>
<div class="drawer-container">
    <ul ng-controller="MenuController as ctrl">
        <li><a ui-sref="state1">State1</a></li>
        <li><a ui-sref="state2">State2</a></li>
        <li><a href="" ng-click="ctrl.review()" drawer-toggle="#review">Review</a></li>
    </ul>
    <ui-view></ui-view>
    <div class="drawer drawer-right" id="review">
        <standalone-router id="myRouter"></standalone-router>
    </div>
    <div class="drawer-backdrop"></div>
</div>

<script type="text/ng-template" id="state1.html">
    <p>State1</p>
</script>
<script type="text/ng-template" id="state2.html">
    <p>State2</p>
</script>

CSS

html, body, .drawer-container, .drawer {
    height: 100%;
}

body {
    margin: 0;
}

.drawer-container {
    position: relative;
    overflow: hidden;
}

.drawer {
    background-color: yellow;
    position: absolute;
    top: 0;
    width: 100%;
    z-index: 2;
}

.drawer-right {
    left: 100%;
    transition: all 0.5s;
}

.drawer-right.open {
    left: 10%;
    transition: all 0.5s;
}

.drawer.open + .drawer-backdrop {
    display: block;
    position: absolute;
    z-index: 1;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    background-color: rgba(204, 153, 204, 0.5);
}

JavaScript

var standaloneRouter = angular.module('standaloneRouter', []);
var app = angular.module('app', ['ui.router', standaloneRouter.name]);

app.config(function($stateProvider, $urlRouterProvider, standaloneRoutesProvider) {
    $urlRouterProvider.otherwise('/state1');
    
    $stateProvider.state('state1', {
        templateUrl: 'state1.html',
        url: '/state1'
    });

    $stateProvider.state('state2', {
        templateUrl: 'state2.html',
        url: '/state2'
    });
    
    standaloneRoutesProvider.router('myRouter').route('review1', {
        template: '<p>Hello world</p>'
    });
});

app.controller('MenuController', function MenuController($scope, $location) {
    this.review = function() {
        $location.search({
            myRouter: 'review1'
        });
    };
});

app.directive('drawerToggle', function drawerToggleDirective($location) {
    return function link($scope, $element, $attrs) {
        $element.on('click', function() {
            $element.closest('.drawer-container').find($attrs.drawerToggle).toggleClass('open');
        });
    };
});

app.directive('drawerBackdrop', function drawerBackdropDirective() {
    return {
        restrict: 'C',
        link: function link($scope, $element) {
            $element.on('click', function() {
                $element.siblings('.drawer').removeClass('open');
            });
        }
    };
});

standaloneRouter.directive('standaloneRouter', function standaloneRouterDirective($location, $compile, standaloneRoutes) {
    return {
        restrict: 'E',
        template: '<div></div>',
        link: function($scope, $element, $attrs) {
            $scope.$on('$locationChangeSuccess', changeRoute);
        
            changeRoute();
            
            function changeRoute() {
                var current = $location.search()[$attrs.id];
                var router = standaloneRoutes[$attrs.id];
                
                if (current) {
                    var route =...