简体   繁体   中英

Cannot Bind Dynamic Data in Component Angular 8

Error when component loading dynamic

DynamicBuilderComponent.ngfactory.js:198 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ng-pristine: true'. Current value: 'ng-pristine: false'.

Problem

    after binding json in select2data to select2 component Angular throw exception.

component code

           @Component({
              changeDetection: ChangeDetectionStrategy.OnPush,
              selector: 'select2',

Imported changeDetection in component.

              template: `
                  <div [formGroup]="form">

                    <ng-container>
                        <ng-select2
                          [data]="select2data"
                          [options]="options"
                          [width]="500"

                          [formControlName]="field.code"
                          (keyup)="changed($event.target.value)">
                        </ng-select2>
                    </ng-container>

                  </div>`
            })

select2 component class

            export class Select2Component implements OnInit {
              @Input() field: any = {};
              @Input() form: FormGroup;
              public exampleData: Array<Select2OptionData>;
              public options: Options;
              public value: string[];
              select2data: any;
              public selected: string;

              constructor(public cl: Services,private cd: ChangeDetectorRef) {
                this.options = {
                  width: '258',
                  multiple: true,
                  tags: false
                };
              }

Problem Area After Binding subscribe data in ng select2 component

              changed(search: any) {

               //call service pass search text to service
                return this.cl.searchFunc(search).subscribe(
                  res1 => 
                          this.select2data = res1.data;
                              this.cd.markForCheck(); // marks path
                      }
                    }
                  },
                  error => {
                    console.log('error  = ', error);
                  });
              }

            }

i tried to print this.select2data in console.log its return me json.

Vendor.js

            function expressionChangedAfterItHasBeenCheckedError(context, oldValue, currValue, isFirstCheck) {
                var msg = "ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '" + oldValue + "'. Current value: '" + currValue + "'.";
                if (isFirstCheck) {
                    msg +=
                        " It seems like the view has been created after its parent and its children have been dirty checked." +
                            " Has it been created in a change detection hook ?";
                }
                return viewDebugError(msg, context);
            }

Great Article

https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html

Reference

Expression ___ has changed after it was checked

  • any suggestion is most welcome.

I believe that you put your component select2 inside another component which contains a form which you then pass to select2 for create another <form> tag, is that correct? I mean do you have something like that?

<form [formGroup]="form">
    <!-- Some code -->
    <select2 [field]="something" [form]="form"></select2>
</form>

If so, then your select2 component SHOULD NOT contain re-declaration of form, it should not contain anything related to forms at all. It should be a form control. Please read a post by Netanel Basal on how to create custom form controls. You will need to create ControlValueAccessor for your select2 and wire it up to Angular forms through a custom provider.

The issue you're facing is that since you include form object twice in the DOM data changes are propagated twice as well and you run into issues. There should be only one reference to a specific instance of FormGroup in your templates.

Solution that worked

         @Component({
          changeDetection: ChangeDetectionStrategy.OnPush,
          selector: 'select2',
          export class Select2Component implements OnInit {
            constructor(public cl: Services,private cd: ChangeDetectorRef) {
            this.options = {
              width: '258',
              multiple: true,
              tags: false
            };
          }

Binding function

 changed(search: any) {

           //call service pass search text to service
            return this.cl.searchFunc(search).subscribe(
              res1 => 
                      this.select2data = res1.data;
                      this.cd.markForCheck(); // marks path
                     this.cd.detectChanges();
                  }
                }
              },
              error => {
                console.log('error  = ', error);
              });
          }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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