【问题标题】:Angular VARIED, database-dependent callback after renderAngular VARIED,渲染后依赖于数据库的回调
【发布时间】:2014-03-19 21:34:06
【问题描述】:

在我的博客上,我希望能够有特定于帖子的交互式演示。所以每个帖子都有它的内容和示例演示,这是要呈现到页面的 HTML。

到目前为止,没问题。我创建了一个 render_html 指令:

angular.module("RenderHtml", []).directive "renderHtml", ->
  restrict: "A"
  scope:
    renderHtml: "@"
  link: (scope, element, attrs) ->
    scope.$watch "renderHtml", (newVal) ->
      element.html(newVal)

我这样称呼它:

<div class='example' renderHtml='{{post.example}}'></div>

问题是,我希望 HTML 嵌入并执行 Angular。

所以呈现的示例 HTML 看起来像这样:

<div ng-controller='SpecificExampleCtrl' ng-init='initFunc()'>
  <a ng-click='someFunc()'>Etc</a>
</div>

当页面被渲染时,SpecificExampleCtrl 将被加载,它的 init 函数运行,并且在点击该链接时运行 ng-click。

(我已经辞职了,如果我什至设法让它工作,必须将ng_controller 保存在应用程序中,但如果有人能想出一种方法将它也保存在数据库中,我会欣喜若狂。)

因此,无论如何,我的问题似乎与 [AngularJS: callback after render (work with DOM after render) one) 和其他问题不同。

为了澄清我能够完成的工作——HTML 被呈现为 HTML,但它的任何 Angular 都没有运行,即使被调用的 Controller 确实存在于我的应用程序中。

根据建议进行编辑

angular.module("RenderHtml", []).directive ($compile) "renderHtml", ->
  restrict: "A"
  scope:
    renderHtml: "@"
  link: (scope, element, attrs) ->
    scope.$watch "renderHtml", (newVal) ->
      element.html(newVal)
      $compile(eval(element))

(上面的代码在我写的时候不起作用。它呈现 HTML,但根本不评估角度。)

编辑看起来我应该使用$eval instead of the vanilla eval,但是当我尝试将其注入指令或在不注入的情况下调用它时,站点错误,以及当我注入和使用 $parse ,看起来它做了类似的事情,整个角度模板没有渲染,我没有收到任何错误。

回答

这最终奏效了:

angular.module("RenderHtml", []).directive "renderHtml", ($compile) ->
  restrict: "A"
  scope:
    renderHtml: "@"
  link: (scope, element, attrs) ->
    scope.$watch "renderHtml", (newVal) ->
      linkFunc = $compile(newVal)
      element.html(linkFunc(scope))

编译 html 返回一个函数,它是作用域的一个参数。

【问题讨论】:

  • 使用 '$eval()' 只会解析和查找角度范围内的值。您需要正常的 'eval()' 来执行代码。

标签: angularjs angularjs-directive angularjs-scope


【解决方案1】:

您可以使用 'eval' 执行从数据库中获取的 javascript 以添加控制器。不是角度的$eval,它根据范围进行评估,而是香草javascript eval,它将编译你的代码。这不是很安全,如果用户有任何机会输入 js,您可能不想这样做,因为它将在您网站上的用户上下文中执行。字符串末尾的 f 作为 eval() 的结果将函数作为对象返回。

eval(response.controllerJavascript);

然后你需要$compile你的html。我基于my fiddle this example。最后,您使用$injector 在您的范围内调用您的控制器函数。

指令:

module.directive('compile', function($compile, $injector) {
  var obj = {
    scope: true, // child scope
    link: function(scope, element, attrs) {
      // 1st function returns value, if changed call 2nd
      scope.$watch(
        function(scope) {
          return scope.$eval(attrs.compile);
        },
        function(value) {
          element.html(value);
          $compile(element.contents())(scope);
        }
      );

      scope.$watch(function(scope) {
        return scope.$eval(attrs.compileCode);
      }, function(value) {
        // get 'function' object
        var controller = eval(value);
        if (typeof(controller) == "function") {
          // invoke controller on our child scope
          $injector.invoke(controller, this, { $scope: scope });
        }
      });
    }
  };
  return obj;
});

HTML:

<div ng-app="TestApp" ng-controller="Ctrl" id="divCtrl">
  <label>Name:</label>
  <input ng-model="name"> <br/>
  <label>Html:</label>
  <textarea ng-model="html"></textarea> <br/>
  <label>Js:</label> <textarea ng-model="js"></textarea> <br/>   

  <div compile="html" compile-code="js">Hi {{name}}</div>

  <input type="button" value="Simulate AJAX" ng-click="simulateAjax()">
</div>

控制器:

module.controller("Ctrl", function($scope) {
  $scope.name = 'Angular';
  var code = 'var f = function($scope) { $scope.name = "Ctrl2"; }\r\nf';
  $scope.simulateAjax = function() {
    $scope.html = '<div>Hello {{name}}</div>';
    $scope.js = code;
    code = 'var f = function($scope) { $scope.name = "Ctrl2-next"; }\r\nf';
  };
});

【讨论】:

  • 那会去哪里?我是否在我的角度指令中评估 html?我在哪里调用编译?我在上面试了一下,但我很确定那是错误的。
猜你喜欢
  • 2016-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
  • 2020-06-13
  • 1970-01-01
相关资源
最近更新 更多