简体   繁体   English

AngularJS监视ngForm引用数组以了解$ valid中的更改

[英]AngularJS watch an array of ngForm references for changes in $valid

I have an array of nested subforms (ngForm) within my main form. 我的主表单中有一组嵌套子表单(ngForm)。 Each subform is registered with my form service by pushing them onto an array, and each of the subforms represent a single document within a document package (the entire array). 通过将每个子表单推送到一个数组中,将它们注册到我的表单服务中,并且每个子表单代表一个文档包(整个数组)中的单个文档。 I'm building a progress directive using Google Charts, and I want to know when one of the subforms becomes $valid. 我正在使用Google Charts构建进度指令,我想知道子窗体之一何时变为$ valid。

I've looked into $watch, and know that I can deep watch by setting the third parameter to true, to be notified of any changes within the array to the validity of the subform. 我研究了$ watch,并且知道我可以通过将第三个参数设置为true来进行深入监视,以将数组中子窗体的有效性发生任何更改时通知我。 Is this the best way to do this? 这是最好的方法吗? The deep changes that might occur could be anything, and it seems expensive. 可能发生的深刻变化可能是任何事情,而且看起来很昂贵。 Can I watch just subFormArray[index].$valid for changes? 我可以只观看subFormArray [index]。$进行更改吗?

$scope.$watch('subFormsArray', 
    function( newSubFormsArray, oldSubFormsArray, scope ){
        // loop through newSubFormsArray and check $valid on each index
        // to get new number of completed subforms for progress directive
    }, true);

I could also just set a watch on each subform.$valid using a function and on any changes update the progress chart. 我也可以只在每个subform。$ valid上使用函数设置监视,并在任何更改上更新进度表。

for( var i = 0; i < $scope.subFormsArray; i++ ) {
    $scope.$watch( function() {
        return $scope.subFormsArray[i].$valid;
    },
    function( newValidity, oldValidity ) {
        // loop through newSubFormValidityArray and check $valid on each index
        // to get new number of completed subforms for progress directive
    });
}

Maybe using $watchGroup? 也许使用$ watchGroup? From the docs I can't quite figure out, but it seems to say that I could do this: 从文档中我还不太清楚,但是似乎可以做到这一点:

$scope.$watchGroup( function() {
    var subFormValidity = [];
    for( var i = 0; i < $scope.subFormsArray; i++ ) {
        // create validity array
        subFormValidity.push( $scope.subFormsArray[i].$valid );
    }
    return subFormValidity;
},
function( newSubFormValidityArray ) {
    // loop through newSubFormValidityArray and check $valid on each index
    // to get new number of completed subforms for progress directive
}); 

Would this even work? 这甚至行得通吗? and which solution would be the best choice? 哪种解决方案是最佳选择?

UPDATE Using the first option I can't seem to get the watch to work on changes to form validity, any idea why it isn't working? 更新使用第一个选项,我似乎无法使手表进行更改以形成表格有效性,您知道为什么它不起作用吗? Using console.log I can see it being hit onload a bunch, and initializing properly, but afterwards it doesn't get triggered. 使用console.log,我可以看到它在加载时被击中并正确初始化,但是之后没有被触发。 But if I hardcode the update function, the chart is correctly set, so it is just the $watch that is causing issues. 但是,如果我对更新功能进行硬编码,则图表会正确设置,因此导致问题的只是$ watch。

$scope.$watch( function() {
     return FormService.getSubForms();
}, function ( newSubForms, oldSubForms ) {

    // Total forms available, and default amount of valid subforms
    var totalForms = FormService.getSubForms().length;
    var totalValid = 0;

    // Check subforms for changes to validity
    angular.forEach( newSubForms, function( subForm, key ) {

        if( subForm.$valid ) { 
            totalValid++; 
        }
    });

    // Update number of complete, and incomplete forms
    self.updateChartData( totalValid, totalForms-totalValid );
}, true );

FINAL Got it to work, created an array of expressions based on subform validity instead of passing an array of subforms straight from my service, I believe this is what @PinhasHouri was saying? 最终使它起作用,基于子窗体有效性创建了一个表达式数组,而不是直接从我的服务中传递子窗体数组,我相信这就是@PinhasHouri所说的吗? Not sure why it didn't work the first way, since I was doing a deep watch. 由于我一直在进行深入观察,因此不确定为什么它不能一开始就起作用。 Can anyone explain why? 谁能解释为什么? Either way it works. 无论哪种方式都可以。

$scope.$watch( function() {

     var subforms = [];

     angular.forEach( FormService.getSubForms(), function( subform, key ) {
          this.push( subform.$valid );
     }, subforms);

     return subforms;
}, function ( newSubForms, oldSubForms ) {

    // Total forms available, and default amount of valid subforms
    var totalForms = FormService.getSubForms().length;
    var totalValid = 0;

    // Check subforms for changes to validity
    angular.forEach( newSubForms, function( subForm, key ) {

        if( subForm.$valid ) { 
            totalValid++; 
        }
    });

    // Update number of complete, and incomplete forms
    self.updateChartData( totalValid, totalForms-totalValid );
}, true );

I will post this as an answer, since in the comments it begun to be a little bit too long. 我将其作为答案发布,因为在评论中它开始有点太长了。

It's very close to what I was proposing, I wanted to do like this: 这与我的建议非常接近,我想这样做:

    $scope.$watch(function() {
       //count how many valids you have
        var totalForms = FormService.getSubForms().length;
        var totalValid = 0;

        // Check subforms for changes to validity
        angular.forEach( newSubForms, function( subForm, key ) {

          if( subForm.$valid ) { 
              totalValid++; 
          }
        });
        return totalValid;
    }, function(newCount, oldCount) {
       self.updateChartData(newCount, totalForms - nowCount);
    });

As a rule of thumb I try to avoid as much as I can deep watching, as it incurs an overhead of deep cloning an item and comparing each of it's memebers on each watch call (to appreciate how many times this gets called in an app, try putting console.log before returning totalValid). 根据经验,我会尽量避免深入观察,因为这会产生深度克隆项目并比较每次观察调用中每个成员的开销(以了解在应用程序中被调用多少次,尝试在返回totalValid之前放入console.log。

If you also change the chart when the valid count is the same, then you will have to come up with a bit different logic, but the principle is the same. 如果在有效计数相同的情况下也更改图表,那么您将不得不提出一些不同的逻辑,但是原理是相同的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM