Search code examples
javascriptangularjsangularjs-ng-include

how to dynamically action an angular ng-include command


Is it possible to dynamically add an ng-include element to a HTML page and have it actioned?

I have a Drag N Drop application where you can drag an element onto the page and in the drop zone the element is replaced with a more detailed element. For examples you drag a box that says Calendar and when it is dropped a calendar is presented. To be clear a new Element is created and added to the DOM, it does not exist before the drop.

When the element is dropped, I'm hoping that I can replace it with a chunk of HTML that looks like below. Instead of having the markup defined in a string like it is at the moment which is not very nice:

<div class='panel panel-default'>
  <div class='panel-heading'>
    <h3 class='panel-title'>
      <span class='glyphicon glyphicon-remove'></span>
      WIDGET NAME
      <spanclass='glyphicon glyphicon-cog'></span>
    </h3>
  </div>
  <div class='widgetContainer' ng-include="'widgets/widget.html'"></div>
</div>

When the above HTML is inserted into the page the referenced HTML file is not included.

What I would like to happen is a HTML file is loaded containing the widget markup and included at the appropriate position.

I'm new to Angular so I don't know if this is because:

  • dynamically adding ng-include isn't supported
  • whether I need to do something with the controller to handle this logic
  • should I be using the tag instead of the attribute?
  • it just isn't possible.

Please provide examples with solutions, as I said I'm new to Angular.

Thanks

UPDATE

The code used to created the HTML that I want to dynamically add to the page looks like this

$("#template").append(
    " \
    <div class='panel panel-default'>\
    <div class='panel-heading'>\
    <h3 class='panel-title'>\
    <span style='padding-right: 10px; cursor:pointer;' class='glyphicon glyphicon-remove' onclick='removeElement(this)'></span>\
    " + widgetDetail['serviceName'] + "\
    <span style='float:right; cursor:pointer;' class='glyphicon glyphicon-cog' onclick='toggleWidgetDetail(this)'></span>\
    </h3>\
    </div>\
    <div class='markupContainer' ng-include=\"'widgets/" + id +".html'\"></div>\
    </div>\
    "
);

I've uploaded the complete code to GitHub. The drag and drop aspects are being handled currently by HTML5 javascript, which can be seen in the file /public/javascripts/js_dragndrop.js. The new widget being added to the page (the code above) is in /public/javascripts/jq_dragndrop.js

I'm in the prototyping phase trying to work out the DragNDrop elements so don't expect high quality code :)


Solution

  • I found a way of achieving what I wanted by moving the HTML5 drop and drop code into AngularJS directives and then (using this [ Compile dynamic template from outside of angular ] as a guide) got the html templates being loaded where I wanted them.

    The main code change looks like this:

    angular.element(document).injector().invoke(function ($compile) {
    
      var widgetDetail = widgets[e.dataTransfer.getData('Text')];
    
      var obj = $("#template");
      var scope = obj.scope();
    
      obj.append(
        "<div class='panel panel-default'><div class='panel-heading'><h3 class='panel-title'>\
         <span style='padding-right: 10px; cursor:pointer;' class='glyphicon glyphicon-remove' onclick='removeWidget(this)'></span>\
         " + widgetDetail['serviceName'] + "\
         <span style='float:right; cursor:pointer;' class='glyphicon glyphicon-cog' onclick='toggleWidgetDetail(this)'></span>\
         </h3></div><div class='markupContainer' ng-include=\"'widgets/" + widgetDetail['serviceId'] + ".html'\"></div>\
         "
       );
    
       $compile(obj.contents())(scope);
       scope.$digest();
    });
    

    You can find the full code in the Git Project /public/controllers/template.js if you are interested.