我正在开发一个"小部件"库,该库创建了一个带有可拖动、动态加载的小部件的仪表板。 整体解决方案是使用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 函数的引用。