2017-08-30 189 views
3

我有一个pre标签,带有动态文本(页面加载时未知)。这个文本可能有ng命令。它会看起来像这样:AngularJS:编译特定模板

<pre> 
    Hello <span ng-click="test('args')">world</span> angular-JS! 
</pre> 

由于这些动态代码是不是在加载的页面存在,angularjs不运行它们和功能test('args')将永远不会运行。

所以,我添加了一个名为指令compile-template

function compileTemplate($compile, $parse) 
{ 
    return { 
     link: function (scope, element, attr) 
     { 
      var parsed = $parse(attr.ngBindHtml); 
      function getStringValue() { return (parsed(scope) || '').toString(); } 

      //Recompile if the template changes 
      scope.$watch(getStringValue, function() 
      { 
       $compile(element, null, -9999)(scope); //The -9999 makes it skip directives so that we do not recompile ourselves 
      }); 
     } 
    } 
} 

现在我pre标签是这样的:

<pre compile-template> 
    Hello <span ng-click="test('args')">world</span> angular-JS! 
</pre> 

这是工作好。

的问题时,我的文字像我的文字开始变化:

<pre compile-template> 
    Hello <span ng-click="test('args')">world</span> angular-JS! }} 
</pre> 

当我试图编译该文(“世界,你好角JS}}!”)我得到这个错误:

Error: [$parse:lexerr] http://errors.angularjs.org/1.5.8/$parse/lexerr?p0=Unexpected%20next%20character%20&p1=s%200-0%20%5B%23%5D&p2=%23coordinates%3A21%7C37%7CN%7C87%7C04%7CW%7C%7C%7C%0A%0A%0A%7C%0A%7Cname%3D 
    at angular.js:38 
    at jc.throwError (angular.js:14179) 
    at jc.lex (angular.js:14101) 
    at s.ast (angular.js:14303) 
    at td.compile (angular.js:14771) 
    at kc.parse (angular.js:15700) 
    at g (angular.js:15865) 
    at k (angular.js:12364) 
    at ca (angular.js:9724) 
    at $b (angular.js:8743) 

这是因为与}}破坏的JS代码相关联的“}}”字符串。

例子:https://jsfiddle.net/m69q87eg/

所以,basicly我特林做是为了让<span> s的JS,但没有别的。

我虽然移动compile-template指令是我跨度的一部分。就像这样:

<pre> 
    Hello <span compile-template ng-click="test('args')">world</span> angular-JS! 
</pre> 

但它不工作,因为pre outter HTML就像文字处理。

怎么办?

+1

嗯,你如何填充'pre'标签的内容?因为我尝试过使用['ngBindHtml'](https://docs.angularjs.org/api/ng/directive/ngBindHtml),并且所有工作都按预期进行,没有任何错误。请参阅[fiddle here](https://jsfiddle.net/ymppayhb/3/)。您能否提供[最小,完整和可验证示例](https://stackoverflow.com/help/mcve)? –

+0

当然,这是我的问题:https://jsfiddle.net/m69q87eg/ – No1Lives4Ever

+0

所以这种情况发生,因为它试图解析'{{...}}之间的表达式,当然这是不正确的。所以有一个问题 - 你可以修改你的模板吗?你可以尝试用['ngNonBindable'指令](https://docs.angularjs.org/api/ng/directive/ngNonBindable)来包装这部分,如'(21°37'N 87 ...}})'。如果没有,那么我们需要考虑如何修改您的指令。 –

回答

1

您可以尝试使用自定义的,这将$compile只在属性被设置的标签(使用querySelectorAll() method或您选择的其他一些筛选逻辑)ngBindHtmlCompile指令:

var module = angular.module("demo", []); 
 

 
module.directive('ngBindHtmlCompile', ['$compile', '$parse', function ($compile, $parse) { 
 
    return { 
 
    link: function (scope, element, attr) { 
 
     var parsed = $parse(attr.ngBindHtmlCompile); 
 
     function getStringValue() { return (parsed(scope) || '').toString(); } 
 
     scope.$watch(getStringValue, function (val) { 
 
     element.html(val); 
 
     if (!!attr.compileTags) { 
 
      $compile(element[0].querySelectorAll(attr.compileTags))(scope); 
 
     } else { 
 
      $compile(element, null, -9999)(scope); 
 
     }   
 
     }); 
 
    } 
 
    } 
 
}]); 
 

 
module.controller('Demo', ['$scope', '$window', function Demo($scope, $window) { 
 
    var vm = this; 
 
    
 
    vm.template1 = ` 
 
populations of Eurasia <span>{{vm.untilStr}}</span> 1492, when Christopher Columbus first <span class=\"highlight-1\" ng-click=\"vm.test(2810)\">sailed into Caribbean waters on a quest to find a sea route to Asia. At that time the Western Hemisphere in general was unknown to Europeans. Following the discovery of the islands by Columbus, the area was quickly colonised by several Western cultures (initially Spain, then later</span> 
 

 
In the Yucatan Channel. The same limit as that described for the Gulf of Mexico [A line joining Cape Catoche Light (21°37′N 87°04′W/21.617°N 87.067°W/21.617; -87.067{{#coordinates:21|37|N|87|04|W||| 
 

 

 
| 
 
|name= 
 
}}) -- 1213123 <span class=\"highlight-1\" ng-click=\"vm.test(4117)\">and the extreme of Agujereada </span>`; 
 
     
 
    vm.test = function(args){ $window.alert(args); }; 
 
    vm.untilStr = "until"; 
 
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> 
 

 
<div ng-app="demo" ng-controller="Demo as vm"> 
 
    <pre ng-bind-html-compile="vm.template1" compile-tags="span"></pre>   
 
    <br/> 
 
</div>