Angular 1.5: dynamic component loading

I am trying to create a kind of generic gridview using AngularJS 1.5 and its components. A (pseudo-code) version of what is happening with me now:

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

Now <my-cell-component> can have a basic ng-switch that handles obvious cases, for example, if the value is text or an image or something like that, but since it will be used by many people and in many projects, it is possible that someone wants to do something unusual and / or very specific inside a cell. They can simply compensate for <my-cell-component> with a lot of ng-switch es, but then they mess with the base code, which damages maintainability.

So, ideally, I would like to do something where the developer can additionally provide his own template for a specific field in the metadata, for example. metadata.columns[3].customCellComponentName = 'some-custom-template'; Then <my-row-component> will look something like this:

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

The project automatically puts all the templates in $ templateCache, so template resolution should not be a problem, but there is also a highlighted line with the symbol "???" obviously not working. It demonstrates what I would like to achieve, but I don’t know how to actually do something like this. I reviewed translation, ng-include and other solutions, but none of them provide the ability to dynamically load a template and bind some data to it.

Any ideas are welcome. I would like to stay as far away from too complicated directives. Although they allow you to do a lot, in my experience they are also a nightmare for debugging and maintenance.

Thanks.

+6
source share
1 answer

You can create a directive for your <my-cell-component> so that it either templateUrl or defines templateUrl and uses it. Let me give an example for the latter,

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

So, we have a directive template with ng-include that uses templateUrl defined based on some constants, for example CELL_TYPE .

Now you have a directive that dynamically loads your template based on your attributes!

You can (obviously) get rid of $watch if the dynamic change to templateUrl not applicable to your use case.

0
source

All Articles