Home > Enterprise >  Behavior Subject auto load without click issue
Behavior Subject auto load without click issue

Time:06-01

There is strange issue I'm encountering at first I try to submit form it succeeds without any issue here is an code excerpt below from page.

userRole.ts:

ngOnInit() {
    const userSubscription = this.userManagementService.currentUsersIdValue.pipe(
      switchMap((userId: string) => {
        if (userId.length > 0) {
          return this.userManagementService.getUsers(userId.toString());
        }
        else {
          return this.userDetailsArr;
        }
      }
      )).subscribe((users) => {
        if (users !== null) {
          const sbCreate = this.userManagementService.getUsersRole(users[0].id)
            .subscribe((roles: any) => {
              if (roles.length > 0) {
                this.userRoleList = roles;
                this.ref.detectChanges();
              }
            });
          this.subscriptions.push(sbCreate);
        }
      });
    this.subscriptions.push(userSubscription);
  }

    //// This is the process to submit form data
    onSubmitRole() {
        if (this.userRole.commonForm.invalid) {
          alert('Please fill the form');
          return;
        }

        const roleData = this.userRole.commonForm.value;

        ////This runs first time when I route to this page after re-routing to this page it starts again without clicking button
        const userSubscribe = this.userManagementService.currentUsersIdValue.pipe(
          switchMap((userId: string) => {
            if (userId.length > 0) {
              return this.userManagementService.getUsers(userId.toString());
            }
            else {
              return this.userDetailsArr;
            }
          }
          )).subscribe((users) => {
            if (users !== null) {
              this.authService.currentUserValue.forEach(u => {
                if (roleData.RoleID) {
                  roleData.CompanyID = roleData.CompanyID;
                  roleData.CreatedBy = roleData.CreatedBy;
                  roleData.CreatedDate = roleData.CreatedDate;
                  roleData.LastModifiedDate = new Date().toLocaleString();
                  roleData.DefaultRoleID = '00000000-0000-0000-0000-000000000000';
                }
                else {
                  roleData.RoleID = '00000000-0000-0000-0000-000000000000';
                  roleData.CompanyID = u.companyID;
                  roleData.CreatedBy = u.id;
                  roleData.CreatedDate = new Date().toLocaleString();
                  roleData.LastModifiedBy = u.id;
                  roleData.LastModifiedDate = new Date().toLocaleString();
                  roleData.Internal = true;
                  roleData.RoleTypeCode = 1;
                  roleData.DefaultRoleID = '00000000-0000-0000-0000-000000000000';
                }
    
                const sbCreate = this.userManagementService.upsertUserRole(roleData)
                  .subscribe((response: any) => {
                    if (response.Status === 200) {
                      this.router.navigate(['general-management/viewprofile']);
                    }
                    else {
                      alert(response.Description);
                    }
                  });
                this.subscriptions.push(sbCreate);
              });
            }
            else {
              if (confirm('Please edit/add any user to continue with Role!')) {
                this.router.navigate(['general-management/viewprofile']);
              }
            }
          });
        this.subscriptions.push(userSubscribe);
      }

Now the problem is that at initial of the page userRole.ts when I hit submit to call this method onSubmitRole() it delivers the data to service and then to server, which is OK after success it routes back to mainUser.ts page when I edit a certain list from the main page to reach userRole.ts page then the strange phenomenon happens, it starts this const userSubscribe = this.userManagementService.currentUsersIdValue.pipe from onSubmitRole() this BehaviourSubject will initially start first time but after edit second time back to this page it will automatically start again const userSubscribe = this.userManagementService.currentUsersIdValue.pipe without hitting onSubmitRole().
The process is as follow - mainUser.ts (have list which can be edited to route to next page) --> userRole.ts (which has a form submit button and here is the strange issue is happening) automatically it runs the service second time on edit.

Here is the userRole.Html page

<div *ngIf="!showRolesTable">
  <form [formGroup]="userRole.commonForm" (ngSubmit)="onSubmitRole()">
    <div >
      <label for="RoleName">Role Name</label>
      <input type="hidden" [(ngModel)]="userRole.RoleID" formControlName="RoleID">
      <input type="text" [(ngModel)]="userRole.RoleName" formControlName="RoleName" id="RoleName" placeholder="Enter Role Name">          
    </div>
    <div >
      <label for="Description">Description</label>
      <input type="text" [(ngModel)]="userRole.Description" formControlName="Description" 
        id="Description" placeholder="Enter Description">
    </div>
    <button type="submit" >Submit</button>
  </form>
</div>

CodePudding user response:

There's no magic in JS - if no one is calling onSubmitRole() (you put in a debugger statement and it doesn't trigger), then it means that the previous subscription is still active.

When you do const userSubscribe = this.userManagementService.currentUsersIdValue.pipe(...).subscribe(...) you are creating a subscription which will keep listening for changes in currentUsersIdValue. The only possibility is that when you go to userRole page the second time, that observable emits something and causes the previous instance of userRole to trigger whatever that pipe triggers.

As for solutions... 1) Make sure that you're cleaning out the subscriptions when the user leaves the userRole page, that could actually be a leak. 2) add a take(1) operator at the very beginning of the pipe: This operator will automatically unsubscribe once 1 value has been received.

CodePudding user response:

Be sure to unsubscribe from your subscription. Implement OnDestroy() interface in your component then call the subscription.unsubscribe(). Additionally, If you do not need the previous value in your Observable then it is better to use Subject() not BehaviourSubject(). Read more on the different types of Subjects in RxJs

  • Related