AngularJs指令与动态控制器和模板

Ham*_*mad 5 javascript angularjs angularjs-directive angularjs-scope

我想创建一个具有动态控制器的动态视图的指令.控制器和模板视图来自服务器.

指令

var DirectivesModule = angular.module('BPM.Directives', []);
(function () {
    'use strict';

    angular
        .module('BPM.Directives')
        .directive('bpmCompletedTask', bpmCompletedTask);

    bpmCompletedTask.$inject = ['$window'];

    function bpmCompletedTask ($window) {
        // Usage:
        //     <bpmCompletedTask></bpmCompletedTask>
        // Creates:
        // 
        var directive = {
            link: link,
            restrict: 'E',
            scope: {
                type: '=',
                taskdata: '=',
                controllername:'@'
            },
            template: '<div ng-include="getContentUrl()"></div>',
            controller: '@',
            name: 'controllername'
            };
        return directive;

        function link(scope, element, attrs) {
            scope.getContentUrl = function () {
                return '/app/views/TasksViews/' + scope.type + '.html';
            }
            scope.getControllerName = function ()
            {
                console.warn("Controller Name is " + scope.type);
                return scope.type;
            }
        }
    }

})();
Run Code Online (Sandbox Code Playgroud)

我在这里试图使用该指令

<div ng-controller="WorkflowHistoryController as vm">
    <h2>Workflow History</h2>
    <h3>{{Id}}</h3>
    <div ng-repeat="workflowStep in CompletedWorkflowSteps">
        <bpm-completed-task controllername="workflowStep.WorkflowTaskType.DataMessageViewViewName" taskdata="workflowStep.WorkflowTaskOutcome.TaskOutcome" type="workflowStep.WorkflowTaskType.DataMessageViewViewName">
        </bpm-completed-task>
    </div>    
</div>
Run Code Online (Sandbox Code Playgroud)

现在的问题是当指令获取控制器名称时,它将其作为文字字符串而不是参数.

它可行吗?如果它不可行,用控制器创建动态视图并在ng-repeat中动态显示它们的最佳解决方案是什么?

谢谢,

更新20 Jan我刚刚更新了我的代码,以防有人对此感兴趣.所有信用都归@Meligy所有.

第一指令:

(function () {
    'use strict';

    angular
        .module('BPM.Directives')
        .directive('bpmCompletedTask', bpmCompletedTask);

    bpmCompletedTask.$inject = ['$compile', '$parse'];

    function bpmCompletedTask ($compile, $parse) {
        var directive = {
            link: function (scope, elem, attrs) {
                console.warn('in the first directive - before if');
                if (!elem.attr('bpm-completed-task-inner'))
                {
                    console.warn('in the first directive');
                    var name = $parse(elem.attr('controllername'))(scope);
                    console.warn('Controller Name : ' + name);
                    elem = elem.removeAttr('bpm-completed-task');
                    elem.attr('controllernameinner', name);
                    elem.attr('bpm-completed-task-inner', '');
                    $compile(elem)(scope);
                }
            },
            restrict: 'A',
            };
        return directive;        
    }

})();
Run Code Online (Sandbox Code Playgroud)

第二指令

angular
.module('BPM.Directives')
.directive('bpmCompletedTaskInner',['$compile', '$parse',
function ($window, $compile, $parse) {
    console.warn('in the second directive');
    return {
        link: function (scope, elem, attrs) {
            console.warn('in the second directive');
            scope.getContentUrl = function () {
                return '/app/views/TasksViews/' + scope.type + '.html';
            }
        },
        restrict: 'A',
        scope: {
            type: '=',
            taskdata: '=',
            controllernameinner: '@'
        },
        template: '<div ng-include="getContentUrl()"></div>',
        controller: '@',
        name: 'controllernameinner'
    };

}]);
Run Code Online (Sandbox Code Playgroud)

Html

 <div ng-repeat="workflowStep in CompletedWorkflowSteps">
        <div bpm-completed-task controllername="workflowStep.WorkflowTaskType.DataMessageViewViewName" taskdata="workflowStep.WorkflowTaskOutcome.TaskOutcome"
                            type="workflowStep.WorkflowTaskType.DataMessageViewViewName">
        </div>
    </div>
Run Code Online (Sandbox Code Playgroud)

Mel*_*igy 3

更新:

\n\n

我成功了,但它真的很难看。查看:

\n\n

http://jsfiddle.net/p6Hb4/13/

\n\n

您的示例有很多移动部分,因此这个示例很简单,但可以满足您的需求。

\n\n

基本上,您需要一个包装器指令,它接受 JS 对象并转换为字符串属性,然后您可以使用 \xd9\x87\xd9\x89 指令来处理其他所有内容(模板、范围等)。

\n\n

。

\n\n

更新2:

\n\n

内联代码:

\n\n

\r\n
\r\n
var app = angular.module(\'myApp\', []).\r\ndirective(\'communicatorInner\', ["$parse", "$compile",\r\n  function($parse, $compile) {\r\n    return {\r\n      restrict: \'A\',\r\n      template: "<input type=\'text\' ng-model=\'message\'/><input type=\'button\' value=\'Send Message\' ng-click=\'sendMsg()\'><br/>",\r\n      scope: {\r\n        message: \'=\'\r\n      },\r\n      controller: \'@\'\r\n    };\r\n  }\r\n]).\r\ndirective(\'communicator\', [\'$compile\', \'$parse\',\r\n  function($compile, $parse) {\r\n    return {\r\n      restrict: \'E\',\r\n      link: function(scope, elem) {\r\n        if (!elem.attr(\'communicator-inner\')) {\r\n          var name = $parse(elem.attr(\'controller-name\'))(scope);\r\n          elem = elem.removeAttr(\'controller-name\')\r\n          elem.attr(\'communicator-inner\', name);\r\n          $compile(elem)(scope);\r\n        }\r\n      }\r\n    };\r\n  }\r\n]).\r\ncontroller("PhoneCtrl", function($scope) {\r\n  $scope.sendMsg = function() {\r\n    alert($scope.message + " : sending message via Phone Ctrl");\r\n  }\r\n}).\r\ncontroller("LandlineCtrl", function($scope) {\r\n  $scope.sendMsg = function() {\r\n    alert($scope.message + " : sending message via Land Line Ctrl ");\r\n  }\r\n})
Run Code Online (Sandbox Code Playgroud)\r\n
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>\r\n\r\n<div ng-app="myApp">\r\n\r\n<div ng-init="test = {p: \'PhoneCtrl\', l: \'LandlineCtrl\' }">\r\n  <communicator controller-name="test.p" message="\'test1\'"></communicator>\r\n  <communicator controller-name="test.l"></communicator>\r\n\r\n</div>\r\n  \r\n  \r\n</div>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

。

\n\n

原创(现在不相关,但可以帮助其他相关问题)

\n\n

是的,它应该有效。

\n\n

Angular 1.3 的测试:

\n\n

http://jsfiddle.net/p6Hb4/9/

\n\n

需要检查的事项:

\n\n
    \n
  • 控制器是否已定义并添加到模块中?不起作用

    \n\n

    如果控制器只是一个全局函数,它将无法工作。必须通过以下方式添加<myModule>.controller("<controllerName>", <functiion>)API添加

  • \n
  • 做ng-controller?只需将其添加到模板中即可

    \n\n

    同样,直接在指令之外使用 ng-controller 是否有效?

  • \n
\n