Rohan Büchner Rohan Büchner - 7 months ago 37
AngularJS Question

Angular (1.5.8) Dynamic Components

I'm trying to build a sort of dynamic dashboard using Angular 1.5.8. I've made decent progress up until the final hurdle. Which is actually rendering the dynamic component.

I've tried 2 options, either adding a

ui-view
and programatically passing in the name of the widget, or, and this is the route I'm guessing is more correct, I need to figure out how to render a dynamic widget.

EG: As I append and item to the
dashItems
collection, it should render a new widget (based on the name I've provided)

I have seen that I can swap out templates using
ngInclude
, but I'm still unclear as to how to get a template and controller to be injected dynamically. (EG all my templates wont be sharing a common controller).

JavaScript:

angular
.module('myDashboard', [])
.config(routesConfig)
.component('dashboard', {
templateUrl: 'dashboard/dashboard.tpl.html',
controller: dashboardController
})
.component('widgetPie', {
template: '<h3>Pie Graph</h3>',
controller: function($log) {
$log.info('widgetPie: loaded');
}
})
.component('widgetLine', {
template: '<h3>Line Graph</h3>',
controller: function($log) {
$log.info('mnWidgetLine: loaded');
}
});

function routesConfig($stateProvider) {
// this is only needed if I go the ui-view route.. I assume
$stateProvider
.state('widgetPie', { component: 'widgetPie'})
.state('widgetLine', { component: 'widgetLine'});
}

function dashboardController($log) {
$log.info('in dashboard');
this.dashItems = [
{ widget:'widgetPie' },
{ widget:'widgetLine' }
];
}


Markup (dashboard/dashboard.tpl.html):

<div>
<ul>
<li ng-repeat="item in dashItems">
<!--somehow render dynamic-->
<!--<widget-pie></widget-pie>-->
<!--<div ui-view="item.widget"></div>-->
</li>
</ul>
</div>


Question(s):

1.
I've looked into
ngInclude
, but to be perfectly honest, I'm not sure how to go about using it in this instance, and IF it is the right tool for this, or am I approaching this incorrectly?

2.
Should I even be adding items to the state provider for this, EG i / could a widget be seen as a child state (thus I'm not sure what would be seen as best practice)

Answer Source

I ended up changing the dashboard.tpl.html file to:

<div>
    <ul>
        <li ng-repeat="item in dashItems">
            <div ng-include="item.widget"></div>
        </li>
    </ul>
</div>

But I also needed to add a build task to run through my widgets folder and generate the following (or you can manually add, whatever floats your boat I guess).

angular
 .module('myDashboard')
 .run(function ($templateCache) {
    $templateCache.put('widgetPie', '<widget-pie></widget-pie>');
    $templateCache.put('widgetLine', '<widget-line></widget-line>');
 });

The above allows me to either use templateUrl, or inline templates.

   .component('widgetPie', {
        templateUrl: 'dashboard/widgetPie.tpl.html',
        controller: function($log) {
            $log.info('widgetPie: loaded');
        }
    })
    .component('widgetLine', {
        template: '<h1>Some Content</h1>',
        controller: function($log) {
            $log.info('widgetLine: loaded');
        }
    })