用于加载路径的自定义角度指令

时间:2015-03-18 11:13:12

标签: angularjs angularjs-directive angularjs-routing

基本上,我需要的是ngView的替代方法,它允许我在html元素中加载自定义路由。

例如,这条路线:

$routeProvider.when('/some/path', {
    templateUrl: 'some/template.html',
    controller: someController,
    controllerAs: 'ctrlAlias'
});

使用此指令(使用myRoute='/some/path'):

<div routeView="myRoute" />

导致:

<div ng-controller="someController as ctrlAlias" ng-include src="some/template.html" />

由于兼容性和传统限制,我无法使用ui-router。 如何使用指令(或其他方式)实现此目的?

1 个答案:

答案 0 :(得分:0)

所以,我调整了ngView中的代码来完成我需要的工作。 它不是很优雅,因为角度路由器模块有很多代码重复,但它工作得很好。 请注意,这仅适用于具有templateUrl的路由和不带参数的路由。

用法:

<div route-view="'/my/route'"></div>
<div route-view="myRoute"></div>

代码:

angular.module('app', [])
    .directive('routeView', routeViewDirective)
    .directive('routeView', routeViewFillContentDirective)

function routeViewDirective($animate, $parse, $q, $route, $sce, $templateRequest) {
    return {
        restrict: 'EA',
        terminal: true,
        priority: 400,
        transclude: 'element',
        link: routeViewDirectiveLink
    };

    function routeViewDirectiveLink(scope, $element, attributes, ctrl, $transclude) {
        var model = $parse(attributes.routeView);
        var currentScope;
        var currentElement;

        scope.$watch(model, update);

        function cleanupLastView() {
            if (currentScope) {
                currentScope.$destroy();
                currentScope = null;
            }
            if (currentElement) {
                $animate.leave(currentElement);
                currentElement = null;
            }
        }

        function update(path) {
            var route = $route.routes[path];

            if (route && route.templateUrl) {
                var newScope = scope.$new();
                var clone = $transclude(newScope, function(clone) {
                    $animate.enter(clone, null, currentElement || $element);
                    cleanupLastView();
                });

                currentElement = clone;
                currentScope = newScope;
            } else {
                cleanupLastView();
            }
        }
    }
}

function routeViewFillContentDirective($compile, $controller, $parse, $q, $route, $sce, $templateRequest) {
    return {
        restrict: 'EA',
        priority: -400,
        link: routeViewFillContentDirectiveLink
    };
    function routeViewFillContentDirectiveLink(scope, $element, attributes) {
        var path = $parse(attributes.routeView)(scope);
        var route = $route.routes[path];
        var templateUrl = route && $sce.getTrustedResourceUrl(route.templateUrl);

        if (angular.isDefined(templateUrl)) {
            $templateRequest(templateUrl).then(function(template) {
                $element.html(template);
                var link = $compile($element.contents());

                if (route.controller) {
                    var controller = $controller(route.controller, { $scope: scope });
                    if (route.controllerAs) {
                        scope[route.controllerAs] = controller;
                    }
                    $element.data('$ngControllerController', controller);
                    $element.children().data('$ngControllerController', controller);
                }

                link(scope);
            });
        }

    }
}