2016-04-11 2 views
6

J'essaie de créer une sorte de gridview générique en utilisant AngularJS 1.5 et ses composants. Une version (pseudocode) de ce que j'ai passe en ce moment:Angular 1.5: charger dynamiquement un composant

// inside <my-grid-component data="data" metadata="metadata"> 
<div ng-repeat="item in $ctrl.data"> 
    <my-row-component item="item" metadata="$ctrl.metadata"></my-row-component> 
</div 

// inside <my-row-component item="item" metadata="metadata"> 
<div ng-repeat="column in $ctrl.metadata.columns"> 
    <my-cell-component value="$ctrl.item[column]"></my-cell-component> 
</div> 

Maintenant <my-cell-component> pourrait avoir une déclaration ng-switch de base qui gère les cas évidents, comme si la valeur est un texte ou une image ou quelque chose, mais depuis cela sera utilisé par beaucoup de gens et sur de nombreux projets, il est possible que quelqu'un veuille faire quelque chose de fantaisie et/ou de très spécifique à l'intérieur d'une cellule. Ils pourrait juste ammend <my-cell-component> avec plus ng-switch es, mais alors ils jouent avec le code de base qui nuisent à la maintenabilité. Donc, idéalement, je voudrais faire quelque chose où un développeur peut éventuellement fournir son propre modèle personnalisé pour un champ spécifique dans les métadonnées, par exemple. metadata.columns[3].customCellComponentName = 'some-custom-template'; Alors <my-row-component> ressemblerait à quelque chose comme ceci:

<div ng-repeat="column in $ctrl.metadata.columns"> 
    <div ng-if="!column.isCustomCellComponent"> 
     <my-cell-component value="$ctrl.item[column]"></my-cell-component> 
    </div> 
    <div ng-if="column.isCustomCellComponent"> 
??? --> <column.customCellComponentName value="$ctrl.item[column]"></column.customCellComponentName> 
    </div> 
</div> 

Le projet met automatiquement tous les modèles en $ templateCache, donc la résolution du modèle ne devrait pas être un problème, mais à part ça, la ligne marquée avec le « ?? ? " de toute évidence ne fonctionne pas. Cela montre ce que je voudrais accomplir, mais je ne sais pas comment faire quelque chose comme ça. J'ai regardé dans la transclusion, ng-include et d'autres solutions, mais aucune ne semble offrir l'option de charger dynamiquement un modèle ET de lier certaines données à un modèle.

Toutes les idées sont les bienvenues. Je voudrais rester aussi loin des directives trop complexes que possible. Bien qu'ils vous permettent de faire beaucoup de choses, dans mon expérience, ils sont aussi un cauchemar de débogage et de maintenabilité.

Merci.

Répondre

0

Vous pouvez créer une directive pour votre <my-cell-component> de sorte qu'il accepte un templateUrl ou détermine le templateUrl et l'utilise. Permettez-moi de vous donner un exemple pour ce dernier,

angular.module('myApp') 
    .directive('myCellComponent', ['CELL_TYPE', function (CELL_TYPE) { 
     return { 
      restrict: 'E', 
      scope:{ 
       cellType: '=' 
      }, 
      template: '<div ng-include="templateUrl"></div>', 
      link: function (scope) { 
       function setTemplate(cellType) { 
        scope.templateUrl = CELL_TYPE[cellType.value].templateUrl; 
        // or figure out some other way to determine templateUrl 
       } 
       scope.$watch(function() { 
        return scope.cellType; 
       }, function (newVal) { 
        if(newVal) { 
         setTemplate(scope.cellType); 
        } 
       }); 
      } 
     }; 
}]); 

Donc, nous avons le modèle de la directive ayant une ng-include qui utilise le templateUrl déterminé sur la base de certaines constantes, par exemple CELL_TYPE.

Maintenant, vous avez une directive qui charge dynamiquement son modèle en fonction de vos attributs!

Vous pouvez (évidemment) vous débarrasser de $watch si le changement dynamique du templateUrl ne s'applique pas à votre cas d'utilisation.