1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Anuncie Aqui
    Anuncie aqui você Também: fdantas@4each.com.br

Getting error while convert existing code to use signal in HttpClient put method (Angular 20)

Discussão em 'Angular' iniciado por Basit, Agosto 11, 2025.

  1. Basit

    Basit Guest

    I am new to Angular. I started with Angular 19 that were using zone.js for change detection. But then I moved to Angular 20 and now I am using zoneless. I have a put method call that I am trying to convert using Signals. Here is the code without using signal.

    Cart.ts

    export interface Cart {
    id: number;
    products: { productId: number }[];
    }


    CartService:

    @Injectable({
    providedIn: 'root'
    })
    export class CartService {

    // cart property to keep a local cache of the user cart
    cart: Cart | undefined;

    addProduct(id: number): Observable<Cart> {

    const cartProduct = { productId: id, quantity: 1 };

    return defer(() =>
    !this.cart
    ? this.httpClient.post<Cart>(this.fakeStoreCartUrl, { products: [cartProduct] })
    : this.httpClient.put<Cart>(`${this.fakeStoreCartUrl}/${this.cart.id}`, {
    products: [
    ...this.cart.products,
    cartProduct
    ]
    })
    ).pipe(map(cart => this.cart = cart));
    }
    }


    then there is a guard which looks like:

    export const checkoutGuard: CanDeactivateFn<CartComponent> = (component, currentRoute, currentState, nextState) => {

    const dialog = inject(MatDialog);
    const cartService = inject(CartService);

    if (cartService.cart) {

    const confirmation = dialog.open(
    CheckoutComponent,
    { data: cartService.cart.products.length }
    ).afterClosed();

    return confirmation;
    }

    return true;

    };


    Here is the route in which it is using.

    export const routes: Routes = [
    ....
    {
    path: 'cart',
    component: CartComponent,
    canActivate: [authGuard],
    canDeactivate: [checkoutGuard]
    },
    ...
    ]


    After converting to zoneless I noticed that this checkoutGuard is no longer working. I tried to convert it to using Signal so change detection work. But I am getting an error. Here is what I did:

    export class CartService {

    cart = signal<Cart | undefined>(undefined);

    addProduct(id: number): Observable<Cart> {

    const cartProduct = { productId: id, quantity: 1 };

    return defer(() => // error
    !this.cart
    ? this.httpClient.post<Cart>(this.fakeStoreCartUrl, { products: [cartProduct] })
    : this.httpClient.put<Cart>(`${this.fakeStoreCartUrl}/${this.cart()?.id}`, {
    products: [
    ...this.cart()?.products, // error
    cartProduct
    ]
    })
    ).pipe(map(cart => this.cart.set(cart)));
    }
    }


    I also change the checkoutGuard.ts

    export const checkoutGuard: CanDeactivateFn<CartComponent> = (component, currentRoute, currentState, nextState) => {

    const dialog = inject(MatDialog);
    const cartService = inject(CartService);

    // Access a signal within the component to check for unsaved changes
    if (cartService.cart()) {

    const confirmation = dialog.open(
    CheckoutComponent,
    { data: cartService.cart()?.products.length }
    ).afterClosed();

    return confirmation;
    }

    return true;
    };


    But now I am getting errors at in CartService

    ...this.cart()?.products, --> Type '{ productId: number; }[] | undefined' must have a '[Symbol.iterator]()' method that returns an iterator.ts(2488)


    At return

    Type 'Observable<void>' is not assignable to type 'Observable<Cart>'. Type 'void' is not assignable to type 'Cart'.ts(2322)


    I am checking ...this.cart()?.products, with Optional Chaining. All other places it is working but at this line I am getting error.

    Also after setting value to signal. Error is return type is Observable instead of Observable. May be there is a better solution but as I said I am new to Angular so I want to understand the cause of error as well as if there is a better solution.

    Thanks

    Continue reading...

Compartilhe esta Página