<body data-ng-app="rxApp">
    <div data-ng-controller="clientController">
        <rx-simple-directive rx-attr-one="one" rx-attr-two="two"></rx-simple-directive>
        <a href="#/one">one</a>
        <a href="#/two">two</a>
        <a href="#/two/five">two point five</a>
        <a href="#/two/six">two point six</a>
        <div data-ng-view=""></div>
    </div>

    <script id="templateOne" type="text/ng-template">
        <div class="Box" id="BoxOne">
            <h2>one</h2>
            <p data-ng-repeat="o in clientVM.data | filter:vm.filterOne">{{o.en}}</p>
            <rx-simple-directive></rx-simple-directive>
        </div>
    </script>

    <script id="templateTwo" type="text/ng-template">
        <div class="Box" id="BoxTwo">
            <h2>dos</h2>
            <p data-ng-repeat="o in clientVM.data | filter:vm.filterTwo">{{o.es}}</p>
            <rx-simple-directive></rx-simple-directive>
        </div>
    </script>

    <script id="templateForSimpleDirective" type="text/ng-template">
        <p>Hello, world!</p>
        <p>
            <span data-ng-if="vm"> [View Model ID: {{vm.id}}]</span>
            <span data-ng-if="!vm"> [View Model ID: {{clientVM.id}}]</span>
        </p>
        <p data-ng-if="!vm" data-ng-repeat="o in clientVM.data">{{o.en}} ↔ {{o.es}}</p>
        <p data-ng-if="clientVM.routeId"><strong>Directive has route ID: </strong>{{clientVM.routeId}}</p>
    </script>
</body>
body {
    text-align: center;
}
a {
    display: inline-block;
    margin: 0.5em;
}
.Box {
    display: inline-block;
    margin: 0 auto;
    height: 300px;
    width: 480px;
}
#BoxOne {
    background: #00d0bc;
}
#BoxTwo {
    background: #e59400;
}
.ng-leave {
    margin: 0;
    z-index: 9999;
}
.ng-enter {
    margin: 0;
    z-index: 8888;
}
.ng-enter {  
    -webkit-animation:slideInRight 0.5s both ease-in;
    -moz-animation:slideInRight 0.5s both ease-in;
    animation:slideInRight 0.5s both ease-in;    
}
.ng-leave {
    -webkit-animation: slideOutLeft 0.5s both ease-in;
    -moz-animation: slideOutLeft 0.5s both ease-in;
    animation: slideOutLeft 0.5s both ease-in;
}

/* slide in from the right */
@keyframes slideInRight {
    from    { transform:translateX(100%); }
    to      { transform: translateX(0); }
}
@-moz-keyframes slideInRight {
    from    { -moz-transform:translateX(100%); }
    to      { -moz-transform: translateX(0); }
}
@-webkit-keyframes slideInRight {
    from    { -webkit-transform:translateX(100%); }
    to      { -webkit-transform: translateX(0); }
}

/* slide out left */
@keyframes slideOutLeft {
    to {
        transform: translateX(-100%);
    }
}
@-moz-keyframes slideOutLeft {
    to {
        -moz-transform: translateX(-100%);
    }
}
@-webkit-keyframes slideOutLeft {
    to {
        -webkit-transform: translateX(-100%);
    }
}
/*jslint this, white, browser */
/*global window, _, angular, jQuery */
(function() {
    "use strict";

    var rxApp = angular.module("rxApp", [
        "ngRoute",
        "ngAnimate",
        "rxApp.services",
        "rxApp.controllers",
        "rxApp.directives"
    ]);

    rxApp.config(["$routeProvider",
        function($routeProvider) {
            $routeProvider.when("/one", {
                templateUrl: "templateOne",
                controller: "oneController"
            }).when("/two/:id?", {
                templateUrl: "templateTwo",
                controller: "twoController"
            }).otherwise({
                redirectTo: "/one"
            });
        }
    ]);

    /* Services */
    var doBroadcastService = function() {
        var onRouteChangeSuccess = function($scope, handler) {
            $scope.$on("$routeChangeSuccess", function(e, currrent, previous) {
                handler(e, currrent, previous);
            });
        };
        return {
            onRouteChangeSuccess: onRouteChangeSuccess
        };
    };

    var doDataService = function() {
        return {
            data: [{
                id: 1,
                en: "one",
                es: "uno"
            }, {
                id: 2,
                en: "two",
                es: "dos"
            }, {
                id: 3,
                en: "three",
                es: "tres"
            }, {
                id: 4,
                en: "four",
                es: "quarto"
            }, {
                id: 5,
                en: "five",
                es: "cinco"
            }]
        };
    };

    var services = angular.module("rxApp.services", []);
    services
        .factory("broadcastService", [doBroadcastService])
        .factory("dataService", [doDataService]);

    /* Controllers */
    var doClientController = function($scope, broadcastService, dataService) {
        $scope.clientVM = {
            id: "client-view-model",
            data: dataService.data,
            routeId: null
        };

        broadcastService.onRouteChangeSuccess($scope, function(e, currrent, previous)
        {
            $scope.clientVM.routeId = currrent.params.id;
        });
    };

    var doOneController = function($scope) {
        $scope.vm = {
            id: "one-view-model",
            filterOne: function(value) {
                return value.id > 1;
            }
        };
    };

    var doTwoController = function($scope) {
        $scope.vm = {
            id: "two-view-model",
            filterTwo: function(value) {
                return value.id > 2;
            }
        };
    };

    var controllers = angular.module("rxApp.controllers", []);
    controllers
        .controller("clientController", [
            "$scope",
            "broadcastService",
            "dataService",
            doClientController
        ])
        .controller("oneController", [
            "$scope",
            doOneController
        ])
        .controller("twoController", [
            "$scope",
            doTwoController
        ]);

    /* Directives */
    var doSimpleDirective = function() {
        return {
            link: function(scope, elem, attr) {
                if (scope.vm) {
                    elem.append("<p>Directive compiled inside <code>ng-view</code>.</p>");
                } else {
                    elem.append("<p>Directive compiled outside of <code>ng-view</code>.</p>");
                }

                if (attr && attr.rxAttrOne) {
                    elem.append("<p>Directive has attribute <code>rxAttrOne:</code> " + attr.rxAttrOne + "</p>");
                }

                if (attr && attr.rxAttrTwo) {
                    elem.append("<p>Directive has attribute <code>rxAttrTwo:</code> " + attr.rxAttrTwo + "</p>");
                }
            },
            restrict: "E",
            scope: false,
            templateUrl: "templateForSimpleDirective"
        };
    };

    var directives = angular.module("rxApp.directives", []);
    directives.directive("rxSimpleDirective", [doSimpleDirective]);
}());

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://songhay.blob.core.windows.net/shared-scripts/underscore.js
  2. https://songhay.blob.core.windows.net/shared-scripts-angular/angular.js
  3. https://songhay.blob.core.windows.net/shared-scripts-angular/angular-route.min.js
  4. https://songhay.blob.core.windows.net/shared-scripts-angular/angular-animate.min.js