簡體   English   中英

AngularJs指令與動態控制器和模板

[英]AngularJs Directive with dynamic Controller and template

我想創建一個具有動態控制器的動態視圖的指令。 控制器和模板視圖來自服務器。

指令

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>

現在的問題是當指令獲取控制器名稱時,它將其作為文字字符串而不是參數。

它可行嗎? 如果它不可行,用控制器創建動態視圖並在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;        
    }

})();

第二指令

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/

要檢查的事項:

  • 控制器是否已定義並添加到模塊中? 不起作用

    如果控制器只是一個全局函數,它將無法工作。 它必須通過<myModule>.controller("<controllerName>", <functiion>) API添加

  • ng-controller有效嗎? 只需將其添加到模板中即可

    同樣,在指令工作之外直接使用ng-controller?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM