Javascript Angularjs watch无法处理对象内部的数组
我有一个对象<代码>{Client:[]、Employee:[]、Product:[]、Project:[]、PayPeriod:[]},其中每个数组都由组件通过双向绑定推送和拼接。主控制器连接所有5个阵列,并将它们提供给另一个组件。在上述组件中,我需要观察绑定,但无论我做什么,它都不起作用。这就是我现在拥有的Javascript Angularjs watch无法处理对象内部的数组,javascript,angularjs,arrays,Javascript,Angularjs,Arrays,我有一个对象{Client:[]、Employee:[]、Product:[]、Project:[]、PayPeriod:[]},其中每个数组都由组件通过双向绑定推送和拼接。主控制器连接所有5个阵列,并将它们提供给另一个组件。在上述组件中,我需要观察绑定,但无论我做什么,它都不起作用。这就是我现在拥有的 $scope.$watch('ctrl.parameters', ctrl.Update(), true); ctrl.Update();是一个函数,可以工作。 ctrl.parameters
$scope.$watch('ctrl.parameters', ctrl.Update(), true);
ctrl.Update();是一个函数,可以工作。ctrl.parameters会得到更新,但不会触发$watch 这有点复杂,如果你需要什么,我可以帮你
ctrl.Update = function () {
$.post("/TrackIt/Query.php?Type=getViaParams&EntityType="+ctrl.entity,{Params:ctrl.parameters},function(Data,Status){
if(Status=="success"){
if (Data.Success) {
ctrl.List = Data.Result.Entities;
} else {
AlertService.Alert(Data.Errors[0],false,null);
SessionService.Session(function () {
ctrl.Update();
});
}
$scope.$apply();
}else{
AlertService.Alert("Something is up with the select options",false,null);
}
},'json');
};
编辑1:Par={客户:[],员工:[],产品:[],项目:[],付款期:[]}
5个具有双向绑定的组件= PAR.X(这些是编辑参数)BR> 具有双向绑定的1个组件= PAR(我需要看这里的绑定) 编辑2:
<script>
TrackIT.controller('EntryController', function EntryController($scope, $http, AlertService, SessionService, DisplayService) {
$scope.Parameters = {Client:[],Employee:[],Product:[],Project:[],PayPeriod:[]};
$scope.Values = {};
});
</script>
<style>
entity-select{
float: left;
display: inline;
padding: 0 5px;
}
#SelectParameters{
float: left;
}
</style>
<div ng-app="TrackIT" ng-controller="EntryController">
<div id="SelectParameters">
<entity-select entity="'Client'" ng-model="Values.Client" multi="true" ng-array="Parameters.Client"></entity-select>
<entity-select entity="'Employee'" ng-model="Values.Employee" multi="true" ng-array="Parameters.Employee"></entity-select>
<entity-select entity="'Product'" ng-model="Values.Product" multi="true" ng-array="Parameters.Product"></entity-select>
<entity-select entity="'Project'" ng-model="Values.Project" multi="true" ng-array="Parameters.Project"></entity-select>
<entity-select entity="'PayPeriod'" ng-model="Values.PayPeriod" multi="true" ng-array="Parameters.PayPeriod"></entity-select>
</div>
<br>
<parameter-table entity="'Entry'" parameters="Parameters"></parameter-table>
</div>
TrackIT.component('entitySelect', {
templateUrl: "/Content/Templates/Select.html",
controller: function SelectController($scope, $http, AlertService, SessionService) {
var ctrl = this;
ctrl.Options = [];
ctrl.Display = [];
ctrl.Add = function () {
var Display = {'Label':ctrl.Label(ctrl.ngModel),'Value':ctrl.ngModel};
ctrl.ngArray.push(ctrl.ngModel);
ctrl.Display.push(Display);
};
ctrl.Remove = function (Key) {
ctrl.ngArray.splice(Key, 1);
ctrl.Display.splice(Key, 1);
};
ctrl.$onInit = function() {
$.post("/TrackIt/Query.php?Type=getSelectList&EntityType="+ctrl.entity,null,function(Data,Status){
if(Status=="success"){
if (Data.Success) {
ctrl.Options = Data.Result.Entities;
if(ctrl.ngModel==undefined){
if(ctrl.none){
ctrl.ngModel = "NULL"
}else{
ctrl.ngModel = angular.copy(ctrl.Options[0].Attributes.ID.Value.toString());
}
}
} else {
AlertService.Alert(Data.Errors[0],false,null);
}
$scope.$apply();
}else{
AlertService.Alert("Something is up with the select options",false,null);
}
},'json');
};
ctrl.Label = function(Value) {
for (var prop in ctrl.Options) {
if(!ctrl.Options.hasOwnProperty(prop)) continue;
if(ctrl.Options[prop].Attributes.ID.Value.toString()==Value.toString()){
return ctrl.Options[prop].DisplayName;
}
}
};
},
bindings: {
entity:"<",
multi:"<",
none:"<",
ngModel:"=",
ngArray:"="
}
});
TrackIT.component('parameterTable', {
templateUrl: "/Content/Templates/BasicTable.html",
controller: function ParameterTableController($scope, $http, AlertService, SessionService, DisplayService) {
var ctrl = this;
ctrl.List = {};
ctrl.Update = function () {
$.post("/TrackIt/Query.php?Type=getViaParams&EntityType="+ctrl.entity,{Params:ctrl.parameters},function(Data,Status){
if(Status=="success"){
if (Data.Success) {
ctrl.List = Data.Result.Entities;
} else {
AlertService.Alert(Data.Errors[0],false,null);
SessionService.Session(function () {
ctrl.Update();
});
}
$scope.$apply();
}else{
AlertService.Alert("Something is up with the select options",false,null);
}
},'json');
};
$scope.$watch('ctrl.parameters', ctrl.Update.bind(ctrl), true);
ctrl.$onInit = function() {
DisplayService.DisplayTrigger(function () {
ctrl.Update();
});
ctrl.Update();
}
},
bindings: {
entity: "<",
parameters: "="
}
});
controller('EntryController',函数EntryController($scope,$http,AlertService,SessionService,DisplayService){
$scope.Parameters={客户:[],员工:[],产品:[],项目:[],付款期:[]};
$scope.Values={};
});
实体选择{
浮动:左;
显示:内联;
填充:0 5px;
}
#选择参数{
浮动:左;
}
TrackIT.component('entitySelect'{
templateUrl:“/Content/Templates/Select.html”,
控制器:函数SelectController($scope、$http、AlertService、SessionService){
var ctrl=this;
ctrl.Options=[];
ctrl.Display=[];
ctrl.Add=函数(){
变量显示={'Label':ctrl.Label(ctrl.ngModel),'Value':ctrl.ngModel};
ctrl.ngArray.push(ctrl.ngModel);
ctrl.Display.push(显示);
};
ctrl.Remove=功能(键){
ctrl.ngArray.splice(键1);
ctrl.Display.splice(键1);
};
ctrl.$onInit=函数(){
$.post(“/TrackIt/Query.php?Type=getSelectList&EntityType=“+ctrl.entity,null,函数(数据,状态){
如果(状态=“成功”){
if(Data.Success){
ctrl.Options=Data.Result.Entities;
if(ctrl.ngModel==未定义){
如果(ctrl.none){
ctrl.ngModel=“NULL”
}否则{
ctrl.ngModel=angular.copy(ctrl.Options[0].Attributes.ID.Value.toString());
}
}
}否则{
AlertService.Alert(Data.Errors[0],false,null);
}
$scope.$apply();
}否则{
AlertService.Alert(“选择选项有问题”,false,null);
}
}“json”);
};
ctrl.Label=函数(值){
用于(ctrl.Options中的var prop){
如果(!ctrl.Options.hasOwnProperty(prop))继续;
如果(ctrl.Options[prop].Attributes.ID.Value.toString()==Value.toString()){
返回ctrl.Options[prop].DisplayName;
}
}
};
},
绑定:{
实体:“这里有两个问题
问题1:ctrl
不是作用域上的属性
在看到完整的控制器代码后,我可以看到ctrl
只是this
的别名,默认情况下,该控制器的实例将以$ctrl
的形式发布在作用域上。但是,通过将函数而不是字符串传递到$scope.$watch()
:
所有的函数都是有角度的
您可能不知道,就Angular而言,它总是为每个手表调用一个函数以获取要比较的值
,Angular使用$parse
从该表达式创建函数。这就是Angular如何将字符串转换为绑定、表达式等中的可执行代码
创建的函数只包含一个参数,该参数是计算表达式的“上下文”。您可以将其视为要使用的范围
当您将函数作为第一个参数传递给$scope.$watch()
时,可以有效地节省从字符串创建函数的时间
问题2:指定监视侦听器函数的方式
您的ctrl.Update()
函数只是希望在ctrl.parameters
发生更改时运行的函数
您在$scope.$watch('ctrl.parameters',ctrl.Update(),true);
的代码中所说的是:
对ctrl.parameters
执行深度监视(监视对任何属性的更改),当它更改时,调用调用ctrl.Update()
的结果,这将是一个jQuery承诺,而不是一个函数
相反,您希望将ctrl.Update
函数本身作为第二个参数传递给$scope.$watch()
,以便在检测到更改时调用它。为此,只需传递ctrl.Update
而不是ctrl.Update()
:
注意事项
在这种特殊情况下,使用ctrl.Update
会起作用,因为在该函数中没有使用this
。对于查看此答案的其他人,请注意,当您以这种方式传递函数时,this
绑定(“上下文”)没有像您所期望的那样维护为ctrl
。若要解决此问题,请使用ctrl.Update.bind(ctrl)
,或者将其包装到函数中,以便使用正确的上下文调用它:$scope.$watch('ctrl.parameters',function(){ctrl.Update()},true);
谨慎使用深度/价值表
在Angular应用程序(也称为value watches)中使用deep watches时,你应该非常谨慎。原因是,对于大型对象来说,这是一个非常昂贵的操作,因为Angular必须在每个摘要循环中对对象进行深入比较-遍历
// ES5
$scope.$watch(function () { return ctrl.parameters; }, ctrl.Update, true);
// ES6/Typescript/Babel
$scope.$watch(() => ctrl.parameters, ctrl.Update, true);
$scope.$watch('ctrl.parameters', ctrl.Update, true);
$scope.$watch('ctrl.parameters', ctrl.Update.bind(ctrl), true);