Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular dynamic polymorphic directives

I'm a beginner to Angular but am poking into some slightly more advanced corners to ensure it has the features I need.

Specifically I need to:

  • render a sequence of widgets of different types with each implemented as an independent Angular directive
  • the widget type is determined from the data, not by markup
  • widgets are each defined in a separate file
  • set the scope of the directive to the data for that widget instance

I think I have solved the requirement described below and implemented at http://jsfiddle.net/cUTt4/5/

Questions:

  1. Is this correct, best practice, and reasonably fast?
  2. Any improvements I should add?
  3. It would be better if the widget directives had no explicit reference { item : '=' } to obtain their isolated scope, but their sub-scopes should be built by the renderform directive. How do I do that?

My solution: HTML (Note the Angular templates are in script here due to limitations of 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: '='}
    };

});
like image 322
pwray Avatar asked Sep 23 '26 05:09

pwray


1 Answers

sorry fast answer, not tested :

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

If this is what you're looking for, please improve this answer.

like image 86
DEY Avatar answered Sep 24 '26 21:09

DEY



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!