Angular JS - 将ng-repeat异步应用于添加到DOM的内容

Angular JS -- Applying ng-repeat to things added to the DOM asyncronously

本文关键字:DOM 添加 应用于 JS ng-repeat 异步 Angular      更新时间:2023-09-26

我正在开发一个"小部件"库,该库创建了一个带有可拖动、动态加载的小部件的仪表板。 整体解决方案是使用Angular。 每个小部件都有一个JavaScript文件和一个Jade文件。 对于我们的一些小部件,结果使用角度指令,如 ng-repeat。 下面是一个特定小部件生成的代码:

<tr ng-repeat="account in vmAccountList">
    <td ng-click="showTransactions(account)">{{account.account.accountNumber}}</td>
    <td ng-click="showTransactions(account)">{{account.account.accountDisplayName.defaultNormalAccountName}}</td>
    <td ng-click="showTransactions(account)" ng-if="account.account.acctTypeId==1">{{account.account.runningBalance.amount | currency}}</td>
    <td ng-click="showTransactions(account)" ng-if="account.account.acctTypeId==3">{{account.account.currentBalance.amount | currency}}</td>
    <td ng-click="showTransactions(account)" ng-if="account.account.acctTypeId==4">{{account.account.currentBalance.amount | currency}}</td>
    <td><a ng-click="deleteAccount(account.itemId);" class="btn btn-default btn xs">X</a></td>
</tr>

问题是 ng-repeat 永远不会被处理——生成的小部件只是渲染一行,上面所有的合并标签都到位了,完全不知道数据。 我尝试了许多不同的$scope.$apply和$scope.$digest组合 - 它们都不起作用。 我发现问题在于,当我的小部件被下载时,JADE 渲染并应用 JS,在页面的生命周期中可能太"晚"了,无法拥有 Angular 进程指令。

有没有命令可以手动告诉 Angular 去查找所有 ng 重复并渲染它们? 如果做不到这一点,有没有办法将加载 aync 的东西插入到 DOM 中并让 Angular 应用这些命令?

加载小部件并填充 DOM 的代码:

$.get('/v1/widget/' + name, (data) => {
    var jadeCode = data;
    $.get('/v1/widget/js/' + name, (data) => {
        if(!w)
            w = 2;
        if(!h)
            h = 1;
        if(that._lastX + w > SDB.NumberOfVerticalLanes) {
            that._lastX = 0;
            that._lastY += h;
        }
        var retVal = new Widget(name, domId, that._lastX, that._lastY, w, h, '');   
        var processedWidget = eval(data + "(retVal)");
        processedWidget._jadeFN = jade.compile(jadeCode);
        var content = processedWidget._jadeFN(processedWidget.JadeScope);
        //The 'content variable contains the markup I posted above at this point, and SetContent applies it to the DOM
        processedWidget.SetContent(content);
    });
});

上面代码片段中注释突出显示的 SetContent 方法只是使用 jquery 插入新内容:

this.SetContent = (cnt) => {
    this.Content = cnt;
    $("#" + this.Id).html(cnt);
};

如果我的一些术语(特别是关于 Angular)不正确,我深表歉意,我只是对它有些熟悉,坦率地说,我不是忠实的粉丝。 但是该项目使用它,所以我必须找到一种方法来让它工作。 谢谢!

解决方案最终是使用 Angular 的$compile创建一个数据感知的 DOM 节点,如下所示:

//Step 1:  Create empty widget
var retVal = new Widget(name, domId, that._lastX, that._lastY, w, h, '');   
//Step 2:  Process Widget Javascript
var processedWidget = eval(data + "(retVal)");
//Step 3:  Process the Jade and set the content
processedWidget._jadeFN = jade.compile(jadeCode);
var content = processedWidget._jadeFN(processedWidget.JadeScope);
content = window.compile(content)(processedWidget.JadeScope);
//Angular Black Magic:
if(processedWidget.JadeScope.$apply)
    processedWidget.JadeScope.$apply();
SDB.AddWidget(processedWidget);
processedWidget.SetContent(content);

请注意 $apply 调用和 window.compile 的添加,它只是对 Angular CTOR 中注入的 $compile 函数的引用。