Directive AngularJs avec contrôleur dynamique et modèle


Hammad

Je veux créer une directive qui a une vue dynamique avec un contrôleur dynamique. le contrôleur et la vue modèle proviennent du serveur.

La directive

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

})();

Voici comment j'essaye d'utiliser la directive

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

Le problème maintenant est que lorsque la directive obtient le nom du contrôleur, elle l'obtient en tant que chaîne littérale et non en tant que paramètre.

Est-ce faisable? si ce n'est pas faisable, quelle est la meilleure solution pour créer des vues dynamiques avec ses contrôleurs et les afficher dynamiquement dans ng-repeat?

Merci,

Mise à jour du 20 janvier Je viens de mettre à jour mon code au cas où quelqu'un serait intéressé. Tout le crédit va à @Meligy.

La première directive:

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

})();

La deuxième 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'
    };

}]);

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

Mise à jour:

Je l'ai fait fonctionner, mais c'est vraiment moche. Vérifier:

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

Votre exemple a beaucoup de pièces mobiles, donc celle-ci est simple, mais fait ce que vous voulez.

Fondamentalement, vous avez besoin d'une directive wrapper qui prend l'objet JS et se convertit en une propriété de chaîne, vous pouvez alors utiliser votre directive pour tout le reste (modèle, portée, etc.).

.

Mise à jour 2:

Code en ligne:

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>

.

Original (non pertinent maintenant mais peut aider d'autres problèmes connexes)

Oui, ça devrait marcher.

Un test avec Angular 1.3:

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

Choses à vérifier:

  • Le contrôleur est-il défini et ajouté au module? Ça ne marchera pas

    Si le contrôleur n'est qu'une fonction globale, cela ne fonctionnera pas. Il doit être ajouté via l' <myModule>.controller("<controllerName>", <functiion>)API

  • Ça ng-controllermarche? Il suffit de l'ajouter au modèle

    De même, l'utilisation de ng-controller directement en dehors de la directive fonctionne-t-elle?

Articles connexes


AngularJs - communication entre contrôleur et directive

Furkan Ç Par exemple; GetSwatchCartListFunc: Comment accéder à cette méthode directement à partir de la directive homeController.js (function (App) { var Home = function Home($scope, MemberService) { $scope.GetSwatchCartListFunc = function (patte

Directive et contrôleur MVC Spring AngularJS

NPanda J'essaie d'obtenir un MVC avec Spring et Angular JS et il fonctionne actuellement [enfin, il appelle juste l'index.html donc oui]. Le fait est que lorsque je suis dans mon index.html , je mets simplement un ng-include dans un autre fichier html comme ce

Contrôleur dynamique Angularjs avec paramètre dynamique

Aung Than Oui J'ai utilisé requirejs, angularamd et ui.bootstrap dans mon projet. En cas de formulaire contextuel, j'ai $ uibModal de ui.bootstrap. Mais je ne peux pas passer un paramètre "items" de la résolution. Comment puis-je injecter des paramètres pour l

passer le contrôleur dynamique à la directive angulaire

Yochai Akoka Je connais la syntaxe du contrôleur et du nom mais j'essaie de créer une directive générique qui obtiendra une liste d'éléments et pour chaque élément, je dois spécifier un contrôleur. Voici ma directive principale: function controlPanel() { v