使用数据库中的内联代码

Using inline code from database

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

目前我正在将 edited/editable 数据存储在数据库 table 中。我还将模板定义存储在数据库 table 中。我使用的模板只是以前硬编码的 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>

我已验证模板代码正在页面上加载(通过 "view source")。但是,该模板代码中的 javascript 或 AngularJS 标记在加载后不会执行。

我已经尝试了几个步骤来执行此代码,包括在我的承诺中添加另一个 .then() 以触及模板中的一些变量以强制刷新,以及各种失败的尝试导致如果存在竞争条件,则会延迟流程。运气不好。

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

我在 SO 上看到的最接近的描述是: and Load HTML template from file into a variable in AngularJs 但我无法完全理解他们所说的和我尝试做的事情却没有成功。

更新: 在完成以下之前的回复后,我更接近了。借助来自@Wes H 和@31piy 的信息,我现在已经验证 HTML 已正确加载到页面上(如 Chrome 上开发人员工具中的 "view source" 所见)。然而,各种 Angular 命令(ng-bind-html(renderHtml...))和第三方工具触发器(data-editable)似乎没有被解释Angular,所以我有 HTML 但没有 javascript activity 与之相关。我的猜测是插入的 HTML 模板以某种方式放在 DOM 中,但实际上并未被 Angular(或 javascript)识别和执行。想法?

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

话虽这么说,读完这篇文章后,我看了一下文档:https://docs.angularjs.org/api/ng/service/$templateCache

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

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

$templateCache.get('edit.html')

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

希望对您有所帮助!

假设所有相关配置都在您的 AngularJS 应用程序中完成,在我看来,您根本不需要使用 $templateCache。为什么?您希望数据库中的 HTML 模板设置在您的 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 模块。

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

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

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

如果将 <script></script> 块替换为:

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

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

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

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