This is a simple angularjs component that allows you to create dynamically controlled modules.

Added by: Sam Deering





Stars: 0

Watchers: 0

Forks: 0

Module Description


This is an experimental module that allows you to create an element whose structure is as dynamic as its content. It requires that you pass it an object with the following structure:

var myStructure = {
    name: 'myUniqueStructureName',
    template: '<h1>Header!</h1><p>Model: {{model}}',
    style: 'h1 { color: #f00; }',
    controller: 'function($scope) { $scope.model = "This was my content: " + $scope.content.payload; }'

var myContent = {
    payload: "foobar";

Once you've done that, this:

<dynamic structure="myStructure" content="myContent"></dynamic>

will automatically get compiled into this:

<div class="dynamic-component">
    <style scoped>
        h1 { color: #f00; }
    <div ng:Controller="DynamicControllers.myUniqueStructureName">
        <p>Model: foobar</p>

Due to the magic of databinding, if you change the 'style' property of myStructure then a new style will be applied reactively without changing anything else in your dynamic element. If you change the 'template' or 'controller' properties then you still get a reactive update but it will be forced to re-draw the state of the element. Depending on the complexity of your element this may or may not be desireable - if you're building a full-fledged mini app that maintains its own state just be aware that you'll lose the inner state if you update the template or controller.

Also note that your controller function becomes a fully-integrated member of your angular app. You can use dependency injection to pass in custom services, you can access the properties of the parent scope (see how we got the myContent value there?), etc etc etc.

The point of this utility is that you can now store entire angular modules somewhere other than your file system. No requirejs, no convoluted folder structure, no dependency nightmares - just pull in your element's template, style and controller as strings and you're good to go. As a side benefit, every part of your component can now be dynamically generated by some other part of your app, which could lead to some cool patterns. :)

Current Requirements and Known Issues

Please note that for this to work a few things have to be true:

  1. 'myStructure' and 'myContent' are bound to objects on a parent controller's scope - this way, updates to these objects are captured and a rerender is forced.

  2. I'm using the experimental scoped style. This is an HTML5 standard but is not implemented almost anywhere yet. It restricts the style provided to the element in which the style block is found, which is way useful. To enable styles, turn on the Experimental Webkit Features flag in chrome://flags

  3. I am adding one object, DynamicControllers, to the global scope. I don't want to be doing this but I don't see any other way right now to bind a controller to a compiled element. It would be great if angular let us do something like $compile(myTemplate)(scope, controller) where if you pass a controller it'll automatically assign it as the controller for the top-level object in the provided template. That would be much cleaner.

  4. Finally, right now I am using new Function(myStructure.controller) which is really just a wrapper for eval. This may raise some security concerns. I'd love to get some feedback on a safer way to do this.

Module stats last updated: 2015-04-19 02:30:06

Disclaimer: Some data on this page may have been gathered from the authors GitHub respository. If you see any mistakes or outdated information please let us know. Thanks!