2

I have the controller that loads template from the server. Controller receives the template by http and compiles it to the valid html. All is fine but js-calls.

My template contains href's/buttons with href-javascript/onclick actions. Here is simplified snippet:

/*global angular */
var app = angular.module("app", ["ngSanitize"]);
app.controller('app.core.ctrl', function($scope, $rootScope, $interpolate) {
  "use strict";
  $scope.check = 1;
  $scope.fetchContent = function() {
    $scope.content = $interpolate(
      '<a href="http://example.com">not interesting link</a>'+
      '<a href="javascript:callSuperLogic();"> My business template link {{check}}</a>' +
      '<button onclick="callSuperLogic();"> My business template button {{check+1}}</button>'
    )($scope);
  };

  $scope.fetchContent();
});

var callSuperLogic = function() {
  "use strict";
  alert('It works!!!');
};
a,
button {
  display: block;
}
div {
  border: 1px solid #A6A6A6;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular-sanitize.min.js"></script>
<div ng-app="app">
  <div ng-controller="app.core.ctrl">
    My template calls:
    <div ng-bind-html="content"></div>
  </div>
</div>

I've tried $sce.trustAsResourceUrl('javascript:callSuperLogic();'); but it didn't help.

Is there any way to call js-event from compiled template?

UPD1: Found workaround: ng-include This behaves as predicted. But this way I can not make any error processing.

Globber
  • 575
  • 3
  • 14

1 Answers1

1

If ngInclude does not fit your needs, the best approach would be using a directive, so you can have direct access to the element and put the content inside with jQuery:

module.directive('myTemplate', function() {
  return {
    compile: function(tElement) {
      var html = '<button onclick="clickme()">Click me!</button>';
      tElement.replaceWith(html);
    }
  };
});

In this case

<my-template></my-template>

becomes

<button onclick="clickme()">Click me!</button>

If you are getting the template with a ajax call, you have to use the $compile service (and this can be done from the link function):

module.directive('myTemplate', function($http, $compile) {
  return {
    link: function(scope, element, attrs) {
      $http.get(attrs.url).then(function(res) {
        tElement.replaceWith($compile(res.data)(scope));          
      });
    }
  };
});

You can use this like:

<my-template url="myurl/template.html"></my-template>

EDIT:

to reload when url changes: http://plnkr.co/edit/j0nVOm

Mario Lamacchia
  • 1,703
  • 1
  • 13
  • 19
  • Nice advice! This looks like "My own ngInclude with blackjack". You can improve your annswer with url="{{someValue}}" and reloading with $scope.someValue = newUrl. Will I be able to update my content manualy by my controller action? I want to write some interactive data editing with content updates. Is there any way to update content of an element on the fly? – Globber Dec 07 '15 at 13:45
  • Updated, I couldn't use code snippets to make ajax calls – Mario Lamacchia Dec 07 '15 at 14:45
  • Is there any way to update content of an element on user action? I want to update code like inline-editor. – Globber Dec 08 '15 at 08:50
  • It is updating the content on user action already, what do you mean? – Mario Lamacchia Dec 08 '15 at 10:54
  • Mean that I want to make some WYSIWYG with content update on user events like ng-click. This way I need to push my update to the server and then poll it again with link update. It means that sontent is uploaded and downloaded. – Globber Dec 08 '15 at 13:43