Angular signals not updating select value

Discussão em 'Angular' iniciado por kibet, Agosto 7, 2025.

  1. kibet

    kibet Guest

    I have a reusable angular component that handles cursor based pagination. However, the select value never changes on the HTML side, yet the change detection works.

    Example, select options are 10, 25, 50. I can select my option as 25 and my page size updates. However the UI still reads as 10. So I cannot go back to the default page size of 10.

    See code below:

    Pagination component

    import {
    ChangeDetectionStrategy,
    Component,
    computed,
    input,
    model,
    Output,
    signal
    } from '@angular/core';
    import { EventEmitter } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { CursorPaginationInput } from '@generated-types';

    @Component({
    selector: 'app-cursor-pagination',
    imports: [FormsModule],
    template: `
    <div class="p-4 flex items-center justify-between">
    <div>
    <label>
    Items per page:
    <select [value]="itemsPerPage()" (change)="onItemsPerPageChange($event)">
    @for (size of [10, 25, 50, 100]; track size) {
    <option [value]="size">{{size}}</option>
    }
    </select>
    </label>
    </div>

    <div class="flex items-center gap-2">
    <button
    class="btn"
    (click)="goToPrevious()"
    [disabled]="!hasPreviousPage()"
    >
    ← Previous
    </button>

    <button
    class="btn"
    (click)="goToNext()"
    [disabled]="!hasNextPage()"
    >
    Next →
    </button>
    </div>
    </div>
    `,
    changeDetection: ChangeDetectionStrategy.OnPush
    })
    export class CursorPaginationComponent {

    hasNextPage = input.required<boolean>();
    hasPreviousPage = input.required<boolean>();
    startCursor = input<string | undefined>(undefined);
    endCursor = input<string | undefined>(undefined);

    itemsPerPage = signal(10);
    str = computed(() => console.log(this.itemsPerPage(), 'lalala'));


    @Output() paginationChange = new EventEmitter<CursorPaginationInput>();

    goToNext() {
    if (this.hasNextPage() && this.endCursor()) {
    this.paginationChange.emit({
    after: this.endCursor(),
    first: this.itemsPerPage(),
    });
    }
    };

    goToPrevious() {
    if (this.hasPreviousPage() && this.startCursor()) {
    this.paginationChange.emit({
    before: this.startCursor(),
    last: this.itemsPerPage(),
    });
    }
    };

    onItemsPerPageChange(event: Event) {
    const newSize = parseInt((event.target as HTMLSelectElement).value, 10);
    this.itemsPerPage.set(newSize);
    this.paginationChange.emit({
    first: newSize,
    });

    };
    }



    Parent component

    @let paginationMeta = (formsRxResorce.value())?.pageInfo;

    <app-cursor-pagination
    [hasNextPage]="paginationMeta!.hasNextPage"
    [hasPreviousPage]="paginationMeta!.hasPreviousPage"
    [startCursor]="paginationMeta.startCursor!"
    [endCursor]="paginationMeta.endCursor!"
    (paginationChange)="onPaginate($event)"
    ></app-cursor-pagination>

    export class ManageFormsComponent {
    cursorPaginationInputType = signal<CursorPaginationInput>({
    after: undefined,
    before: undefined,
    first: 10,
    last: 10,
    });
    formsRxResorce = rxResource({
    stream: () => this.getForms,
    params: () => this.cursorPaginationInputType(),
    });


    onPaginate(event: CursorPaginationInput) {
    viewTransitionsFn(() => this.cursorPaginationInputType.set(event));
    }

    }

    Continue reading...

Compartilhe esta Página