Refactor component with Signals

Discussão em 'Angular' iniciado por Dreidel, Dezembro 17, 2024.

  1. Dreidel

    Dreidel Guest

    I'm using Angular 17 and started now to apply Signals and whatever I can to in future versions, as 19 says, make zoneless angular applications and etc.

    So, here I am, but, I'm confused to how apply some refactors, like for this list product component, so this is some of the questions I have trying to change the code:

    We have the bindProducts/brands to fill the variables, so I see I can use toSignal() to get the pure array as signal, but this leads me to the following problem:

    • What if I want to remade the GET? How I will rebind the products and brands signal arrays?
    • How I will use this products/brands from the signal to fill my Material datasource.data with this data? (considering angular doesn't encourage using effect()). I was thinking about computed() but this is used to create a variable readonly signal, not just do something when some signal value change

    Here my current component (resumed)

    @Component({
    selector: 'app-list-products',
    templateUrl: './list-products.component.html',
    styleUrls: ['./list-products.component.scss'],
    standalone: true,
    imports: [MaterialModule, FormsModule, ButtonComponent, RouterModule, ResultComponent],
    })
    export class ListProductsComponent implements OnInit, AfterViewInit {
    dataSource = new MatTableDataSource<Product>([]);
    searchSubject = new Subject<string>();

    productFilter = '';
    brandsSelectionFilter: number[] = [];

    products: Product[] = [];
    brands: Brand[] = [];

    @ViewChild(MatPaginator) paginator: MatPaginator;

    constructor(
    private productsService: ProductsService,
    private branchService: BranchService,
    private dialog: MatDialog,
    private router: Router,
    private toastr: ToastrService
    ) {}

    ngAfterViewInit(): void {
    this.dataSource.paginator = this.paginator;
    this.dataSource.filterPredicate = this.productFilterFn;
    }

    ngOnInit() {
    this.searchSubject.pipe(debounceTime(300)).subscribe(() => this.applyProductFilter());
    this.bindBrandsAndProducts();
    }



    bindBrandsAndProducts() {
    forkJoin([this.branchService.getAllBrands(), this.productsService.getAllProducts()]).subscribe(
    ([brands, products]) => {
    products.forEach((p) =>
    p.imageReferences.forEach((img) => (img.url += `?timestamp=${new Date().getTime()}`))
    );

    this.products = products.slice();
    this.dataSource.data = products.slice();
    this.brands = brands.slice();
    }
    );
    }

    private bindProducts(): void {
    this.productsService.getAllProducts().subscribe((products) => {
    this.products = products.slice();
    this.dataSource.data = products.slice();
    });
    }

    applyProductFilter(): void {
    let filteredProducts = this.products.slice();

    if (this.brandsSelectionFilter.length > 0) {
    filteredProducts = this.products.filter((product) => {
    const productBrandTypes = product.brands.map((b) => b.brandType);
    return productBrandTypes.some((type) => this.brandsSelectionFilter.includes(type));
    });
    }

    this.dataSource.data = filteredProducts;
    this.dataSource.filter = this.productFilter.trim().toLowerCase();
    }

    productFilterFn(data: Product, filter: string): boolean {
    return true;
    }
    }


    And I started with this:

    readonly #productsService = inject(ProductsService);
    readonly #branchService = inject(BranchService);
    readonly #dialog = inject(MatDialog);
    readonly #router = inject(Router);
    readonly #toastr = inject(ToastrService);

    readonly paginator = viewChild.required(MatPaginator);

    readonly dataSource = new MatTableDataSource<Product>([]);
    searchSubject = new Subject<string>();

    productFilter = '';
    brandsSelectionFilter: number[] = [];

    products = toSignal(this.#productsService.getAllProducts(), { initialValue: [] });
    brands = toSignal(this.#branchService.getAllBrands(), { initialValue: [] });

    constructor() {
    afterNextRender(() => {
    this.dataSource.paginator = this.paginator();
    this.dataSource.filterPredicate = this.productFilterFn;
    });
    }


    But again, how would I do these changes? I'm thinking I will have a totally new code flow changing that, so it's a little bit confusing to get all of that changes

    Continue reading...

Compartilhe esta Página