javascript - 带有动态 Controller 和模板的 AngularJs 指令

标签 javascript angularjs angularjs-directive angularjs-scope

我想创建一个带有动态 Controller 的动态 View 的指令。 Controller 和模板 View 来自服务器。

指令

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;
            }
        }
    }

})();

这里是我尝试使用指令的方式

<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>

现在的问题是当指令获取 Controller 名称时,它将它作为文字字符串而不是作为参数获取。

可行吗? 如果不可行,使用其 Controller 创建动态 View 并在 ng-repeat 中动态显示它们的最佳解决方案是什么?

谢谢,

1 月 20 日更新 我刚刚更新了我的代码,以防有人对此感兴趣。所有功劳归于@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;        
    }

})();

第二指令

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'
    };

}]);

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>

最佳答案

更新:

我让它工作了,但它真的很难看。检查:

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

您的示例有很多动人的部分,所以这个示例很简单,但可以满足您的要求。

基本上,您需要一个包装器指令来获取 JS 对象并将其转换为字符串属性,然后您可以将指令用于其他所有内容(模板、范围等)。

.

更新 2:

内联代码:

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

<div ng-app="myApp">

<div ng-init="test = {p: 'PhoneCtrl', l: 'LandlineCtrl' }">
  <communicator controller-name="test.p" message="'test1'"></communicator>
  <communicator controller-name="test.l"></communicator>

</div>
  
  
</div>

.

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

是的,它应该有效。

Angular 1.3 测试:

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

要检查的事情:

  • Controller 是否已定义并添加到模块中?它不会工作

    如果 Controller 只是一个全局函数,它将无法工作。它必须通过 <myModule>.controller("<controllerName>", <functiion>) 添加接口(interface)

  • 是否 ng-controller工作?只需将其添加到模板中即可

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

关于javascript - 带有动态 Controller 和模板的 AngularJs 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28021748/

相关文章:

javascript - 我可以向 requirejs 模块添加一个方法作为另一个模块的依赖项,并在每次模块作为依赖项加载时都可用吗?

javascript - 如何正确清除Interval

javascript - 自定义自动完成 Angular Material

javascript - angularjs 中有多少种限制可用

angularjs - Angularstrap - 模态框

Javascript facebook 登录 - 安全登录的最佳方式是什么?

javascript - jsPDF 将 PDF 附加到邮件

javascript - Angular JS 下拉菜单使用 ng-click 和 ng-show 显示动态内容?

css - 单击按钮时,我正在尝试为按钮添加颜色。按钮在 ng-repeat 下

javascript - 如何访问指令中的范围集合对象以手动构造 HTML 片段?