2014-01-15 3 views
3

Я начинаю с угловатым, но втираюсь в несколько более продвинутые углы, чтобы обеспечить ему необходимые функции.Угловые динамические полиморфные директивы

Конкретно мне нужно:

  • делает последовательность виджетов различных типов с каждым реализованным в качестве независимых угловых директив
  • типа виджета определяется из данных, а не по разметке
  • виджетов каждый определяется в отдельном файле
  • задает область действия директивы для данных для этого экземпляра виджета

Я думаю, что я решил требования, описанные ниже, и реализованный в http://jsfiddle.net/cUTt4/5/

Вопросы:

  1. это правильно, лучшая практика, и достаточно быстро?
  2. Любые улучшения, которые я должен добавить?
  3. Было бы лучше, если бы директивы виджета не имели явной ссылки {item: '='}, чтобы получить свою изолированную область видимости, но их под-области должны быть построены директивой renderform. Как мне это сделать?

Мое решение: HTML (Обратите внимание на угловые шаблоны в сценарии здесь из-за ограничений jsfiddle)

<div ng-app="myApp"> 

    <script type="text/ng-template" id="widget-type-a"> 
     <div> 
      <label>{{ item.label}} </label> 
      <input type="text" ng-model="item.val" > 
     </div> 
    </script> 

    <script type="text/ng-template" id="widget-type-b"> 
     <div> 
      <label>{{ item.label}}</label> 
      <input type="text" ng-model="item.val" > 
     </div> 
    </script> 

    <div ng-controller="FormCtrl"> 
     <renderform></renderform> 
    </div> 
</div> 

main.js:

var app = angular.module('myApp', []); 

function FormCtrl($scope) { 
    items = [ 
     { 
      type: 'widget-type-a', 
      label : 'Widget A instance 1', 
      val: 1 
     }, 
     { 
      type: 'widget-type-b', 
      label : 'Widget B instance 1',  
      val : 2 
     }, 
     { 
      type: 'widget-type-a', 
      label : 'Widget A instance 2', 
      val : 3 
     } 
    ]; 
    $scope.items = items 

} 

app.directive('renderform', function($compile) { 
    function linkFn(scope, element) { 
     var item, 
      itemIdx, 
      templStr = '', 
      newParent, 
      data, 
      newEl; 

     newParent = angular.element('<div></div>') 
     for(itemIdx in scope.items) { 
      item = items[itemIdx]; 
      templStr += '<div ' + item.type + ' item="items[' + itemIdx + ']"></div>'; 
     } 
     newEl = angular.element(templStr); 
     $compile(newEl)(scope); 
     element.replaceWith(newEl); 
    } 

    return { 
     restrict: 'E', 
     link:linkFn 

    }; 

}); 

app.directive('widgetTypeA', function() { 
    return { 
     restrict: 'A', 
     templateUrl: 'widget-type-a', 
     scope: { item: '=' } 
    }; 

}); 

app.directive('widgetTypeB', function() { 
    return { 
     restrict: 'A', 
     templateUrl: 'widget-type-b', 
     scope: { item: '='} 
    }; 

}); 
+0

Ваш jsfiddle, кажется, вызывает несколько ошибок. –

+0

Спасибо, Michal, я не сохранил параметры загрузки. Ссылка выше должна теперь работать в FF/Chrome. – pwray

ответ

3

извините быстрый ответ, не испытания:

<div data-ng-repeat="item in items"> 
    <div data-ng-switch data-on="item.type"> 
    <div data-ng-switch-when="widget-type-a" data-widget-type-a="item"></div> 
    <div data-ng-switch-when="widget-type-b" data-widget-type-b="item"></div> 
    </div> 
</div> 

Если это то, что вы ищете, пожалуйста, улучшите этот ответ.

+0

См. Https://docs.angularjs.org/api/ng/directive/ngSwitch – Eldloppa

1

Я думал об этой проблеме в течение некоторого времени и, хотя опция ng-switch работает для простых случаев, она представляет собой довольно накладные расходы на обслуживание.

Я придумал решение, которое позволяет использовать одну точку обслуживания. Рассмотрим следующий пример:

var app = angular.module('poly', []); 
 

 

 
app.controller('AppController', function ($scope) { 
 
    $scope.items = [ 
 
     {directive: 'odd-numbers'}, 
 
     {directive: 'even-numbers'}, 
 
     {directive: 'odd-numbers'} 
 
    ]; 
 
}); 
 

 

 
app.directive('component', function ($compile) { 
 
    return { 
 
     restrict: 'E', 
 
     controller: function() { 
 

 
     }, 
 
     controllerAs: 'component_ctrl', 
 
     link: function (scope, element, attrs) { 
 
      var child_directive = scope.$eval(attrs.directive); 
 
      var child_element = $compile('<' + child_directive + ' data="data"></' + child_directive + '>')(scope); 
 
      element.append(child_element); 
 
     } 
 
    } 
 
}); 
 

 

 
app.directive('oddNumbers', function ($interval) { 
 
    return { 
 
     restrict: 'E', 
 
     link: function (scope) { 
 
      scope.number = 0; 
 
      $interval(function() { 
 
       scope.number += 2; 
 
      }, 1000); 
 
     }, 
 
     template: '<h1>{{ number }}</h1>' 
 
    } 
 
}); 
 

 

 
app.directive('evenNumbers', function ($interval) { 
 
    return { 
 
     restrict: 'E', 
 
     link: function (scope) { 
 
      scope.number = 1; 
 
      $interval(function() { 
 
       scope.number += 2; 
 
      }, 1000); 
 
     }, 
 
     template: '<h1>{{ number }}</h1>' 
 
    }; 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<section ng-app="poly" ng-controller="AppController"> 
 
    <div ng-repeat="item in items"> 
 
    <component directive="item.directive" data="item.data"></component> 
 
    </div> 
 
</section>

Это позволяет компонентам быть указаны в контроллере в специальном пути и ретранслятор, не имея делегировать ответственность через коммутатор.

NB Я не реализовал, как данные передаются между компонентами

Смежные вопросы