动态控制器和templateUrl注入Angular指令

时间:2015-04-29 07:35:42

标签: angularjs dynamic angularjs-directive controller

我很难找到制定完全动态指令的解决方案。我使用angular-gridster库来概述仪表板页面的图块。我想通过灵活的指令动态加载一些特定的磁贴。

<div gridster="vm.model.gridsterOptions">

    <ul>
        <li gridster-item="tile.tileParams.gridParams" ng-repeat="tile in vm.model.dashboards.tiles">

            <div class="box" ng-controller="tileGrid_TileController">

                <eg-tile template-url={{tile.tileEngine.tempUrl}}
                         controller-name={{tile.tileEngine.tileCtrl}}>
                </eg-tile>

            </div>

        </li>
    </ul>

</div>

我创建了egTile指令:

(function () {
    function implementation() {
        return {
            restrict: 'E',
            transclude: true,
            scope: true,
            controller: '@',
            bindToController:true,
            controllerAs: 'vm',
            name: 'controllerName',
            templateUrl: function (elem, attrs) {
                return attrs.templateUrl || 'app/module/tileGrid/view/templates/empty.html';
            }

        };
    }
var declaration = [implementation];
angular.module('app.tileGrid').directive('egTile', declaration);
}());

如果我在egTile指令中使用固定字符串,如

,该指令将起作用
<eg-tile template-url="string_url" controller-name= "string_ctrl"></eg-tile>

但我想动态选择控制器和templateUrl。 我已经尝试使用$ parse和$ observe服务但没有成功。 这甚至可以使指令如此灵活吗?

提前致谢

1 个答案:

答案 0 :(得分:0)

我找到了解决问题的方法.....

我使用了2个额外的指令,它们将为“灵活指令”egTile提供控制器字符串和templateUrl-string。

一个用于创建控制器字符串:

(function () {
function implementation($compile, $parse) {
    return {
        restrict: 'A',
        scope: true,
        terminal: true,
        priority: 99999,
        link: function (scope, elem) {
            var name = $parse(elem.attr('eg-parse-controller'))(scope);
            elem.removeAttr('eg-parse-controller');
            elem.attr('controller-name', name);
            $compile(elem)(scope);
        }
    };
}

var declaration = ['$compile', '$parse', implementation];
angular.module('app').directive('egParseController', declaration);

}());

一个用于创建模板字符串:

(function () {
function implementation($compile, $parse) {
    return {
        restrict: 'A',
        scope: true,
        terminal: true,
        priority: 99998,
        link: function (scope, elem) {
            var name = $parse(elem.attr('eg-parse-template'))(scope);
            elem.removeAttr('eg-parse-template');
            elem.attr('template-url', name);
            $compile(elem)(scope);
        }
    };
}

var declaration = ['$compile', '$parse', implementation];
angular.module('app').directive('egParseTemplate', declaration);
}());

我可以用它作为:

<div gridster="vm.model.gridsterOptions">

<ul>
    <li gridster-item="tile.tileParams.gridParams" ng-repeat="tile in vm.model.dashboards.tiles" ng-controller="tileGrid_TileController">

        <eg-tile tile="tile"
                eg-parse-template=tile.tileEngine.tempUrl
                eg-parse-controller='tile.tileEngine.tileCtrl'>
        </eg-tile>
    </li>
</ul>

使用指令定义:

(function () {
function implementation($parse) {
    return {
        restrict: 'E',
        transclude: true,
        scope: {
            tile : '='
        },
        controller: '@',
        bindToController:true,
        controllerAs: 'vm',
        name: 'controllerName',
        templateUrl: 'app/module/tileGrid/view/tileTemplate.html',
        link: function(scope, element, attrs) {
          scope.getContentUrl = function() {
              return attrs.templateUrl || 'app/module/tileGrid/view/templates/empty.html';
          }
        }

    };
}

var declaration = ['$parse' , implementation];
angular.module('app.tileGrid').directive('egTile', declaration);
}());

使用tileTemplate.html:

<div class="box">

    <div class="box-header">
       <h3>{{ vm.tile.tileParams.title }}</h3>
       <div class="box-header-btns pull-right">
           <a title="Remove widget" ng-click="vm.removeTile(tile)">
                <i class="fa fa-trash"></i>
        </a>
    </div>

    </div>
    <div class="box-content">
        <div ng-include="getContentUrl()"></div>
    </div>
</div>

有了这个方法,我可以完全访问我在动态加载控制器和动态加载视图中传递给egTile指令的磁贴。 欢迎所有评论。