【问题标题】:Using inline code from database使用数据库中的内联代码
【发布时间】:2017-11-22 23:06:00
【问题描述】:

在我的应用程序的一部分中,我有一个用户正在编辑单页信息(通过 HTML 编辑器:内容工具)。我已经开始修改该功能代码,以便他们正在编辑的页面使用动态模板构建,而不是硬编码。

目前我将已编辑/可编辑的数据存储在数据库表中。我还将模板定义存储在数据库表中。我使用的模板只是之前硬编码的 HTML 代码,所以我知道模板是有效的。

此时,我可以正确地从服务器接收到 JSON 包装器中的所有数据。不工作的是呈现内容——页面保持空白。我确定问题在于我对 AngularJS 及其执行方式缺乏了解。

[更新:在使用@Wes H 和@31PIY 的输入重新处理后,代码和以下执行描述已更新。显然,不再是 $templateCache 问题。] 具体来说,我的 HTML 是:

<body ng-app>
    <div ng-controller="PageEditController">
        <div ng-bind-html="renderHtml(htmlTemplate)"></div>
    </div>
</body>

[注意:renderHtml 是我对 $sce.TrustAsHtml() 的包装,以确保 HTML 不会被 Angular 剥离]

我的 javascript 的相关部分是:

        $http({
            method: 'POST',
            url: 'https://my-api-access-point',
            data: parms
        }).then(function successCallback(response) {
                var resp = response.data['Items'];
                var data = {};
                if (resp)
                    data = resp[0];
                console.log("jsLoadScreen Data: ", data);
                $scope.models.fields = data;
                console.log('replacing template: ', $scope.models.fields['template']);
                $scope.htmlTemplate = $scope.models.fields['template'];

控制台输出为:

jsLoadScreen Data: {UID:"1"
 left:"<h1>↵    One↵</h1>"
 right:"<h2>↵    Two↵</h2>"
 screenId:"1"
 template:"        <div class="row">↵            <div class="column">↵                <div data-editable data-name="left" ng-bind-html="renderHtml(models.fields.left)">↵                </div>↵            </div>↵            <div class="vl"></div>↵            <div class="column">↵                <div data-editable data-name="right" ng-bind-html="renderHtml(models.fields.right)">↵                </div>↵            </div>↵        </div>"

replacing template:         <div class="row">
            <div class="column">
                <div data-editable data-name="left" ng-bind-html="renderHtml(models.fields.left)">
                </div>
            </div>
            <div class="vl"></div>
            <div class="column">
                <div data-editable data-name="right" ng-bind-html="renderHtml(models.fields.right)">
                </div>
            </div>
        </div>

我已验证页面上正在加载模板代码(通过“查看源代码”)。但是,一旦加载,模板代码中的任何 javascript 或 AngularJS 标记都不会执行。

我已经尝试了几个步骤来执行此代码,包括在我的承诺中添加另一个.then() 以触摸模板中的一些变量以强制刷新,以及各种导致进程延迟的不幸尝试万一有比赛条件。没有运气。

对于AngularJS,我是否处于如此陌生的水域,我应该放弃并在服务器端组合模板和数据,并使其成为一个单一的AJAX操作,而不是尝试做两步:(1)AJAX插入新的HTML模板,一旦插入然后 (2) AJAX 将新数据插入新的 HTML 模板?或者我应该对新插入的模板(或在插入模板时)做些什么来将其注册为 javascript 执行的东西?

我在 SO 上看到的最接近的描述是:How $templateCache works?Load HTML template from file into a variable in AngularJs,但我无法完全理解他们所说的内容以及我未成功尝试做的事情。

更新: 在完成了以下先前的回复后,我更接近了。使用来自@Wes H 和@31piy 的信息,我现在已经验证了 HTML 已正确加载到页面上(如 Chrome 开发人员工具中的“查看源代码”所示)。但是,Angular 似乎无法解释各种 Angular 命令(ng-bind-html(renderHtml...))和第 3 方工具触发器(数据可编辑),因此我有 HTML 但没有与相关的 javascript 活动它。我的猜测是插入的 HTML 模板以某种方式放入了 DOM 中,但实际上并未被 Angular(或 javascript)识别和执行。想法?

【问题讨论】:

    标签: angularjs templates browser-cache


    【解决方案1】:

    假设所有相关配置都在您的 AngularJS 应用程序中完成,在我看来,您根本不需要使用$templateCache。为什么?您希望在您的 HTML 中设置来自 DB 的 HTML 模板(如果我理解正确的话)。

    为此,您可以简单地使用 ng-bind-html 将 HTML 内容绑定到模板中的 HTML 元素。这是一个例子:

    $http.post('https://my-api-access-point', parms)
      .then(function successCallback(response) {
        // ... Your code
        // Assign the template to a scope variable here
        $scope.htmlTemplate = $scope.models.fields['template'];
        // ... Your code
      });
    

    现在,作用域中有一个变量htmlTemplate,可以像这样直接绑定到HTML模板:

    <div ng-bind-html="htmlTemplate"></div>
    

    这样,htmlTemplate 的内容将出现在div 元素下。您需要确保在您的应用中正确配置了ngSanitize 模块。

    【讨论】:

    • 这里有很好的信息,并且与@Wes H 一起工作,我能够更接近。我已经用更多信息更新了我上面的帖子。
    【解决方案2】:

    $templateCache - 正如您列出的第一个 link 所述,它用作任何模板 URL 请求(如 templateUrl、ng-include 等)的缓存实用程序。

    除此之外,您还可以使用 $templateCache 作为键值缓存存储。当您使用 $templateCache.put('KEY', 'HTML string') 时,任何模板 URL 请求都会在发出网络请求之前检查存储的密钥。在您的情况下,您手动将商店添加到键“edit.html”中,因此它将始终检索您的值。键可以是任何唯一的字符串,但不一定是文件名。

    根据文档,您尝试执行的操作应该有效。但是,在 AngularJs 中包含模板(缓存或不缓存)的典型方法是使用 ngInclude。

    如果您将 &lt;script&gt;&lt;/script&gt; 块替换为:

    <div ng-include="'edit.html'"></div>
    

    将呈现来自$scope.models.fields['template'] 的 HTML 和任何绑定。请注意键周围的额外引号。

    另一个潜在的棘手部分是确保在您尝试访问ng-include 中的缓存模板之前解决$http 返回的承诺。这就是 31piy 建议使用 ng-bind-html 的地方,它监视 $scope 并在承诺解决时更新,可能更简单。

    【讨论】:

    • 这里有很好的信息,但是 ng-include 确实会创建一个无限循环,因为它似乎会在重新加载时重新触发。我不知道细节原因,但@31piy 的 ng-bind-html 似乎让我更接近。我已经用更多信息更新了我上面的帖子。
    【解决方案3】:

    首先,免责声明...我根本不了解 AngularJS,所以对此持保留态度!

    话虽如此,读完之后,我查看了文档:https://docs.angularjs.org/api/ng/service/$templateCache

    看起来您已经通过直接使用$templateCache 服务以声明方式创建了缓存。现在,您需要通过以下方法之一来渲染它:

    myApp.component('myComponent', {
       templateUrl: 'edit.html'
    });
    

    $templateCache.get('edit.html')
    

    此外,由于您直接使用服务,因此不需要脚本标记。根据文档,您可以采用一种方法或另一种方法。

    希望有帮助!

    【讨论】:

      【解决方案4】:

      除了@31piy 和@Wes H 提到的重组之外,最后一步是使用带有指令的$compile。在此处找到解决方案:Compiling dynamic HTML strings from database

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多