Search code examples
angularformssubscription

Angular. Form control values from subscription


I have a form which has to look like this: enter image description here Values of userGroups are taken from Web Api and here I faced a problem. I implement function that uses subscription and gets User Groups from http. Form is created in the constructor. In this case (obviously) the value of userGroups is undefined because it was assigned in subscription.

export class UserAddComponent implements OnInit {
userForm: FormGroup;
userGroups: UserGroup[];

constructor(
    private http: HttpService,
    private fb: FormBuilder) {
        this.userForm = fb.group({
            'login': ['', [Validators.required]],
            'userGroups': this.fb.array(this.userGroups.map(x => !1)) // userGroups is undefined
        });
    }

    private getUserGroups() {
        this.http.get<ODataResponse>(`${this.soddApiUrl}/UserGroups`)
            .subscribe({
                next: (data: ODataResponse) => {
                    this.userGroups = <UserGroup[]>data.value;
                },
                error: () => { },
                complete: () => { }
            });
    }

    get login() { return this.userForm.get('login'); }
}

I tried another approach - to create form in subscription:

export class UserAddComponent implements OnInit {
userForm: FormGroup;
userGroups: UserGroup[];

constructor(
    private http: HttpService,
    private fb: FormBuilder) {
        this.http.get<ODataResponse>(`${this.soddApiUrl}/UserGroups`)
            .subscribe({
                next: (data: ODataResponse) => {
                    this.userGroups = <UserGroup[]>data.value;

                    this.userForm = fb.group({
                        'login': ['', [Validators.required],
                        'userGroups': this.fb.array(this.userGroups.map(x => !1))
                    });
                },
                error: (err) => { },
                complete: () => { }
            });
    }
  
    get login() { return this.userForm.get('login'); } // userFrom is undefined
}

In this case form is created fine but I get login is undefined error in template (because userForm value was assigned in subscription).

<form [formGroup]="userForm" (ngSubmit)="addUser()">
<div>
    <label for="login" class="label">Login</label>
    <input type="text" nbInput fullWidth id="login" formControlName="login"
          <!-- login is undefined here -->
          [status]="login.dirty ? (login.invalid  ? 'danger' : 'success') : 'basic'"
          [attr.aria-invalid]="login.invalid && login.touched ? true : null" />
</div>

<div>
    <label class="label">User Groups</label>
    <div *ngFor="let userGroup of userGroups; let i = index" formArrayName="userGroups">
        <nb-checkbox [formControlName]="i">{{userGroup.Title}}</nb-checkbox>
    </div>
</div>

So, in the first case I can't get access to array which values assigned in subscription, in the second case I can't get the value of form control because is is out of subscription.

Is there any solution to get it worked?

Thank you!


Solution

  • move the form creation to OnInit method

    ngOnInit() {
      this.createForm();
    }
    
    private createForm() {
        this.userForm = fb.group({
            'login': ['', [Validators.required]],
            'userGroups': this.fb.array((this.userGroups || []).map(x => !1)) // add empty array to avoid undefined error
        });
    }
    

    then in subscribed method call again the create form

    yourHttpMethod() {
       this.http.get<ODataResponse>(`${this.soddApiUrl}/UserGroups`)
            .subscribe({
                next: (data: ODataResponse) => {
                    this.userGroups = <UserGroup[]>data.value;
    
                    this.createForm();
                },
                error: (err) => { },
                complete: () => { }
            });
    }
    

    if you can't lose the initial subscription then use the patchform in subscribe.