我正在尝试编写一些代码来检测角度中复杂嵌套的分层对象的更改。我希望$watch
或$watchCollection
表达式就足够了,但事实证明这很难实现。
有人可以提出一个解决问题的好方法吗?
我期待观察的数据结构的一个例子是(在json中):
{
"$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]], VM.ConfigurationServer",
"Name":"DevelopmentEnvironment",
"Descendents":{
"$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]][], VM.ConfigurationServer",
"$values":[{
"$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]], VM.ConfigurationServer",
"Name":"MoreSpecificEnvironment",
"Descendents":{
"$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]][], VM.ConfigurationServer",
"$values":[{
"$type":"<>f__AnonymousType7`2[[System.String, mscorlib],[System.Object, mscorlib]], VM.ConfigurationServer",
"Name":"level3",
"Descendents":null
}]
}
}]
}
}
如您所见,Json Serializer的TypeNameHandling设置为All,这是系统其他部分所必需的。
我需要注意的是,对任何嵌套对象的Name
属性进行了任何更改,并添加或删除了Descendent
。
我试过了两次
scope.$watch(<objectname>, function(){...}, true);
和
scope.watchCollection(<objectname>, function(){...}, true);
这两个属性都会检测顶级Name
和Descendents
属性的更改,但对于嵌套的对象没有任何更改。
根据我的理解,这表明angular.equals
函数没有注意到顶层以下的变化。
有没有办法注入自定义相等比较器?
有没有办法动态更改watchExpression
?因此,将监视应用于层次结构中的每个对象,并在层次结构更改时更改watchExpression
答案 0 :(得分:1)
问题是import pandas as pd, numpy as np
# Set up the test data
df = pd.DataFrame(np.ceil(np.random.rand(1,10)*1000))
values = ["Value_"+str(i) for i in range(5)]
colors = ["Color_"+str(i) for i in range(5)]
df.columns = values + colors
# Order
idx = np.argsort(df[df.columns[5:]].values)[0]
# Reverse (descending order)
ridx = idx[::-1]
df[df.columns[5:][ridx]]
会忽略以angular.equals()
符号开头的密钥,即在您的情况下,$
和$type
会在比较期间被忽略。
除Angulars自己的服务/指令/等外,不要在Angular代码中使用以$标志开头的属性!
Check out this fiddle并尝试将$values
数组重命名为$values
。
答案 1 :(得分:1)
除了@ michael-rose的答案之外,我还添加了一项服务,用于转换webapi收到的数据:
var DataClenseService = function () {
"use strict";
this.renameFields = function (data, fieldRenames) {
if (data == null) {
return null;
}
if (typeof data !== 'object') {
return data;
}
var service = this;
Object.keys(data).forEach(function (propertyName) {
var matchingRenames = fieldRenames.filter(function (rename) { return rename.old === propertyName; });
var currentValue = data[propertyName];
if (matchingRenames.length == 1) {
delete data[propertyName];
data[matchingRenames[0].new] = service.renameFields(currentValue, fieldRenames);
} else {
data[propertyName] = service.renameFields(currentValue, fieldRenames);
}
});
return data;
};
};
并简单地将其称为:
var cleanedData = DataClenseService.renameFields(data, [{ old: '$values', new: 'values' }, { old: '$type', new: 'type' }]);