How do I know when custom form control is marked as pristine in Angular?

后端 未结 3 2022
再見小時候
再見小時候 2020-12-10 04:03

I have several custom form control components in my Angular application, which implement ControlValueAccessor interface and it works great.

However, whe

相关标签:
3条回答
  • 2020-12-10 04:08

    There is another way to check if the form is dirty or not. We can compare the object through which form is bind to.Below function can be used for object properties comparison

    isEquivalent(a, b) {
    // Create arrays of property names
    var aProps = Object.getOwnPropertyNames(a);
    var bProps = Object.getOwnPropertyNames(b);
    
    // If number of properties is different,
    // objects are not equivalent
    if (aProps.length != bProps.length) {
        return false;
    }
    
    for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i];
    
        // If values of same property are not equal,
        // objects are not equivalent
        if (a[propName] !== b[propName]) {
            return false;
        }
    }
    
    // If we made it this far, objects
    // are considered equivalent
    return true;
    

    }

    if you want to check this use below stackblitz link. I have tested it and is working well. Stackblitz link

    0 讨论(0)
  • 2020-12-10 04:29

    Another suggestion, based upon Slava's answer, is to replace the markAsDirty, markAsPristine, and _updatePristine methods in the FormGroup class:

    ngOnInit(): void {
      const markAsDirty = this.formGroup.markAsDirty;
      this.formGroup.markAsDirty = (opts) => {
        markAsDirty.apply(this.formGroup, opts);
        console.log('>>>>> markAsDirty');
      };
      const markAsPristine = this.formGroup.markAsPristine;
      this.formGroup.markAsPristine = (opts) => {
        markAsPristine.apply(this.formGroup, opts);
        console.log('>>>>> markAsPristine');
      };
      const updatePristine = this.formGroup['_updatePristine'];
      this.formGroup['_updatePristine'] = (opts) => {
        updatePristine.apply(this.formGroup, opts);
        console.log('>>>>> updatePristine');
      };
    }
    

    I'm emitting events in the console.log locations, but other approaches would work, of course.

    0 讨论(0)
  • 2020-12-10 04:33

    After thorough investigation I've found out that this functionality is not specifically provided by Angular. I've posted an issue in the official repository regarding this and it's gained feature request status. I hope it will be implemented in near future.


    Until then, here's two possible workarounds:

    Monkey-patching the markAsPristine()

    @Component({
      selector: 'my-custom-form-component',
      templateUrl: './custom-form-component.html',
      providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: MyCustomFormComponent,
        multi: true
      }]
    })
    export class MyCustomFormComponent implements ControlValueAccessor, OnInit {
    
      private control: AbstractControl;
    
    
      ngOnInit () {
        const self = this;
        const origFunc = this.control.markAsPristine;
        this.control.markAsPristine = function () {
          origFunc.apply(this, arguments);
          console.log('Marked as pristine!');
        }
      }
    
    }
    

    Watching for changes with ngDoCheck

    Be advised, that this solution could be less performant, but it gives you better flexibility, because you can monitor when pristine state is changed. In the solution above, you will be notified only when markAsPristine() is called.

    @Component({
      selector: 'my-custom-form-component',
      templateUrl: './custom-form-component.html',
      providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: MyCustomFormComponent,
        multi: true
      }]
    })
    export class MyCustomFormComponent implements ControlValueAccessor, DoCheck {
    
      private control: AbstractControl;
    
      private pristine = true;
    
    
      ngDoCheck (): void {
        if (this.pristine !== this.control.pristine) {
          this.pristine = this.control.pristine;
          if (this.pristine) {
            console.log('Marked as pristine!');
          }
        }
      }
    
    }
    

    And if you need to access the FormControl instance from your component, please see this question: Get access to FormControl from the custom form component in Angular.

    0 讨论(0)
提交回复
热议问题