How can I use angular signals for a lot of side effects

88 Views Asked by At

So, I have the following code

import { Component, computed, model, signal } from '@angular/core'
import { IVillageWiseMember } from '../../../types/IVillageWisemember'
import { IDataWithPagination } from '../../../types/IDataWithPagination'
import { INITIAL_PAGINATION_DATA } from '../../../constants/selectors'
import { HttpClient } from '@angular/common/http'
import { finalize } from 'rxjs'
import { TableSkeletonComponent } from '../../shared/skeleton/table-skeleton/table-skeleton.component'
import { FormsModule } from '@angular/forms'

@Component({
  selector: 'app-member-table',
  standalone: true,
  imports: [TableSkeletonComponent, FormsModule],
  templateUrl: './member-table.component.html',
})
export class MemberTableComponent {
  private readonly API_URL = 'http://localhost:5199'

  loading = signal(true)
  pageSize = signal(10)
  pageNumber = signal(1)

  idSearch = model('')
  nameSearch = model('')
  houseSearch = model('')
  villageSearch = model('')

  memberInfo = signal<IDataWithPagination<IVillageWiseMember[]>>({
    paginationData: INITIAL_PAGINATION_DATA,
    data: [],
  })

  memberData = computed(() => this.memberInfo().data)
  paginationData = computed(() => this.memberInfo().paginationData)

  constructor(private readonly httpClient: HttpClient) {
    this.getMemberInfo()
  }

  public getMemberInfo() {
    let url = `${this.API_URL}/api/v1/Member/GetMemberDetails? 
    pageSize=${this.pageSize()}&pageNumber=${this.pageNumber()}`
    if (this.idSearch().length > 2) {
      url = `${url}&idSearch=${this.idSearch()}`
    }
    if (this.nameSearch().length > 2) {
      url = `${url}&idSearch=${this.nameSearch()}`
    }
    if (this.houseSearch().length > 2) {
      url = `${url}&idSearch=${this.houseSearch()}`
    }
    if (this.villageSearch().length > 2) {
      url = `${url}&idSearch=${this.villageSearch()}`
    }

    this.httpClient
      .get<IDataWithPagination<IVillageWiseMember[]>>(url)
      .pipe(
        finalize(
          () =>
            // setTimeout(() => {
            this.loading.set(false)
          // }, 3000)
        )
      )
      .subscribe(value => {
        this.memberInfo.set(value)
      })
  }

  handlePageChange(page: number) {
    this.pageNumber.set(page)
    this.getMemberInfo()
  }

  public generatePaginationArray(
    currentPageNumber: number,
    currentPageSize: number,
    totalItemCount: number
  ): number[] {
    const pagesToShow = 5
    const halfPagesToShow = Math.floor(pagesToShow / 2)

    const totalPages = Math.ceil(totalItemCount / currentPageSize)

    let startPage = Math.max(1, currentPageNumber - halfPagesToShow)
    const endPage = Math.min(totalPages, startPage + pagesToShow - 1)

    if (endPage - startPage + 1 < pagesToShow) {
      startPage = Math.max(1, endPage - pagesToShow + 1)
    }

    return Array.from(
      { length: endPage - startPage + 1 },
      (_, index) => startPage + index
    )
  }
}

now, as you can see I have a getMemberInfo function that I am using with angular signals, now, during pagination, I am calling the function again and again, now to an extent, that worked, the problem here is that I want this getMemberInfo function to run every time any of those signal changes, that includes the pageNumber, pageSize, or any of those search parameters, but I don't want it to run again when I am changing the memberInfo signal, how can I do that here, I tried to use an effect inside the constructor and it didn't work, so, what is the solution here? Also, I tried this

constructor(private readonly httpClient: HttpClient) {
    effect(
      () => {
        this.getMemberInfo()
      },
      {
        allowSignalWrites: true,
      }
    )
  }

It didn't work

1

There are 1 best solutions below

5
Chellappan வ On

We can achieve this by untracking the memberInfo signal:

effect(
  () => {
     untracked(()=>{
       this.memberInfo();
     })
    this.getMemberInfo()
  },
  {
    allowSignalWrites: true,
  }
)

ForMoreInfo