-1

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 class="form-group">
      <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 class="form-group">
      <label for="Description">Description</label>
      <input type="text" [(ngModel)]="userRole.Description" formControlName="Description" class="form-control"
        id="Description" placeholder="Enter Description">
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
  </form>
</div>
  • 1
    This question is pretty difficult to follow Could do with being more concise – Drenai May 31 '22 at 20:18
  • @Drenai Simply when I'm on the `mainUser.ts` page there are list of data which I can click on edit and move to another page namely this `userRole.ts` on the first time on this page I can submit form data easily and it redirects back to `mainUser.ts` another time I try to attempt edit to return back on the `userRole.ts` it auto submits without me able to click this starts `const userSubscribe = this.userManagementService.currentUsersIdValue.pipe` this is Behaviour subject which is being subscribed everytime on submit. –  May 31 '22 at 20:59
  • Why you have 'this.userManagementService.currentUsersIdValue' subscriptions twice ? – paranaaan Jun 01 '22 at 04:34
  • @paranaaan cause I need to get userId everytime from it that is why and also they call various services from that userId –  Jun 01 '22 at 10:41

2 Answers2

1

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

onrails
  • 778
  • 5
  • 10
  • used like this `ngOnDestroy() { this.subscriptions.forEach(sb => sb.unsubscribe()); }` –  Jun 01 '22 at 13:23
  • There is a better option when you have so many subscriptions (10+ Observables) inside one component and you want to destroy all of them in one go! This forEach is fine but in terms of performance it can be cumbersome. For enterprise clean code, use SubSink library. It is reputable, safe and very clean. Check it out here on NPM (https://www.npmjs.com/package/subsink) – onrails Jun 01 '22 at 15:48
0

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.

olivarra1
  • 3,269
  • 3
  • 23
  • 34