0

I have a 3rd party service with a javascript library that will generate HTML from a JSON-structure. The HTML is generated using a directive that calls on the library methods to generate HTML and then put it as innerHTML.

To extend this I have been able to render a custom HTML-tag that I want to process with my own directive.

If my HTML-file starts with:

<vendor-directive vendorAttr="doStuff"></vendor-directive>

After the vendor library it would then result in:

<vendor-directive vendorAttr="doStuff"><my-custom-component>IDabcd1234</my-custom-component></vendor-directive>

Where my-custom-component have a directive that I have specified, that I want to in turn evaluate and pull in some data async, then output that as a complex component or structure.

End result:

<vendor-directive vendorAttr="doStuff">
    <my-custom-coponent>
        <form><input type="text" ... /></form>
    </my-custom-component>
</vendor-directive>

I have looked around and found some information about $compile but I can't get the whole pictures. Is this supported with AngularJS (latest ver) and what are basic syntax to get this working,

Suggestions and examples warmly welcome! Have a nice day,

Magnus
  • 3,691
  • 5
  • 27
  • 35

2 Answers2

0

Yes, you can use $compile in your controller or directive.

When you know that content is loaded do this

var dynamicDocumentObject = $('vendor-directive');
$compile(dynamicDocumentObject.contents())($scope);

But think about some workaround given your workflow.

For example if you only have to render html but not angular bindings in my-custom-coponent you can:

  • process html element with your vendor's code
  • assign html to some variable content
  • bind html inside vendor-directive using ng-bind-html-unsafe

Also see: Compiling dynamic HTML strings from database

Community
  • 1
  • 1
Nikolay Baluk
  • 2,245
  • 1
  • 19
  • 22
0

See my answer to this question for an example of nested directives.

Since the question being asked is quite different, I will try and give a better explanation here. I'm not entirely sure I understand the question correctly, so I will lay it out as I understand it:

  1. Page loads, the markup for your directive shows nothing in particular.
  2. You grab some data asynchronously.
  3. You process that data and produce some HTML that you then want to append or insert to your directive.

See this fork of my original plnkr. That is just to demonstrate how the transformData directive uses the method of the videoPlayer directive.

The parent directive declared in the require: attribute has its scope passed to the child directive's linking function as controller (the fourth argument). This allows you to expose an API to the child directives on the parent directive's scope.

I would suggest that you don't need to use $compile at all, though the $compile documentation is required reading for writing directives in my opinion. Here are some adjustments that I would make to the plnkr to suit your case:

directive('myCustomComponent', ['$http', '$sce', function($http, $sce) {
  return {
    scope: {
      url: '@',
      output: '@'
    },
    require: '^parentDirective',
    template: '<div ng-bind-html="output"></div>',
    link: function(scope, elem, attrs, controller) {
      $http({
        url: scope.url,
        method: 'GET', // or whatever
      }).
      then(function(r) {
        var html = controller.getHtml(r.data);
        scope.output = $sce.trustAsHtml(html);
      });
    }
  }
}]);

When your app is instantiated and the linking function is executed your async call will be performed and whenever it's finished, this div will be populated with the htmlified return data.

Markup:

<my-custom-component url='//someurl.org' ></my-custom-component>

You could also potentially set some placeholder text through the output attribute of the directive.

Update: After seeing Nikolay Baluk's answer, I had to make some changes to acknowledge that angular doesn't just dump html into the page unless you explicitly tell it to. For this you must use the $sce service (which is built-in). ng-bind-html-unsafe was actually removed in Angular 1.2, but you can get the same behavior with the code as modified above and in my plnkr.

Community
  • 1
  • 1
trey-jones
  • 3,329
  • 1
  • 27
  • 35