Reputation: 1125
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:
I think I have solved the requirement described below and implemented at http://jsfiddle.net/cUTt4/5/
Questions:
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: '='}
};
});
Upvotes: 3
Views: 2352
Reputation: 419
I have been thinking about this problem for some time now and, although the ng-switch
option work for simple cases, it introduces quite a maintenance overhead.
I've come up with a solution which allows for a single point of maintenance. Consider the following:
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>
This allows for the components to be specified in the controller in an ad hoc way and the repeater not having to delegate responsibility via a switch.
NB I didn't implement how the data is passed between components
Upvotes: 2
Reputation: 1810
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.
Upvotes: 3