Open Closed

Angular InputSignal - Run ListService's hookToQuery() on Value Change #10836


User avatar
0
kkmy created

Hello,

How can I use ABP's hookToQuery() pattern with an InputSignal in Angular so that whenever its value is changed, the table should refresh itself? I could not see an example in tutorial documents. What should be the approach in the example below?

Thanks.

export class EagleComponent implements OnInit {

  eagleId = input.required<string>();

  public readonly listService = inject(ListService<GetListEagleDto>);
  private eagleService = inject(EagleService);

  eagles: PagedResultDto<EagleDto> | null = null;

  ngOnInit(): void {
    this.createQueryHook();
  }

  createQueryHook() {
    const req = (query) => this.eagleService.getList({
      ...query,
      eagleId: this.eagleId()
    });

    this.listService.hookToQuery(req).subscribe(res => {
      this.eagles = res;
    });
  }

  query() {
    this.listService.get();
  }
}
Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

4 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • ListService.hookToQuery(...) runs its stream when you call listService.get(). So to refresh the table when an InputSignal changes, the ABP-side pattern is: keep your hookToQuery as-is, and trigger listService.get() from a signal effect() whenever the input changes.
    import { Component, DestroyRef, effect, inject, OnInit, input, untracked } from '@angular/core';
    import { ListService, PagedResultDto } from '@abp/ng.core';
    import { EagleDto, GetListEagleDto, EagleService } from '@proxy/eagles';
    
    @Component({
      // ...
    })
    export class EagleComponent implements OnInit {
      eagleId = input.required<string>();
    
      public readonly listService = inject(ListService<GetListEagleDto>);
      private readonly eagleService = inject(EagleService);
    
      eagles: PagedResultDto<EagleDto> | null = null;
    
      ngOnInit(): void {
        const req = (query) =>
          this.eagleService.getList({
            ...query,
            eagleId: this.eagleId(), // read signal here (fine)
          });
    
        this.listService.hookToQuery(req).subscribe(res => {
          this.eagles = res;
        });
    
        // Re-run query whenever eagleId changes
        effect(() => {
          this.eagleId(); // track changes
          untracked(() => this.listService.get()); // trigger refresh without tracking ListService internals
        });
      }
    }
    
    • Notes:
      • untracked prevents the effect from accidentally re-running due to anything listService.get() touches internally; the only dependency will be eagleId().
      • You don’t need a separate query() method anymore unless you also want a manual refresh button.

    Sources:

    • https://abp.io/docs/10.6/framework/ui/angular/list-service
    • https://abp.io/docs/latest/framework/ui/angular/list-service

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    hookToQuery re-runs its request callback only when the ListService's internal query stream emits (paging, sorting, filter changes or a listService.get() call), so it doesn't react to signal changes by itself. The way to connect them is to trigger listService.get() from an effect whenever eagleId changes:

    import { effect, untracked } from '@angular/core';
    
    constructor() {
      effect(() => {
        this.eagleId();
        untracked(() => this.listService.get());
      });
    }
    

    You can keep the rest of your component as-is. The request callback reads this.eagleId() on every run, so each refresh picks up the current value. One thing to watch out for: create the effect in the constructor — ngOnInit is not an injection context, so effect there throws NG0203 unless you pass an injector.

    With ListService's default 300ms debounce, there is also no duplicate request on the first load — the initial get() from ListService and the effect's first run are debounced into a single request.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    kkmy created

    I have already done it the way you have suggested but I wanted to check just in case :)

    Thank you.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    : )

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 28, 2026, 11:44
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.