2

Note that this is using Angular 18.0.0.

I am updating code to change from an observer to a signal. Instead of watching the observer, I want it passed into the component as if it were @Input. As an intermediate step, I can use a signal this way, with an empty initial value. When an array of several accounts (from an observer) is set to the accounts signal, the total is summed and it works.

accounts = signal(<Account[]>[]);
totalLiquidationValue = computed(() => {
  return this.accounts().reduce((a, acct) => (a += acct.liquidationValue), 0);
});

But if I try to use it as an input signal, it does not even compile:

accounts = input.required<Account[]>;

The error is:

Property 'reduce' does not exist on type '(opts?: InputOptionsWithoutTransform<Account[]> | undefined) => InputSignal<Account[]>'.

I also cannot do this in the template after changing the signal to an input signal:

 *ngFor="let a of accounts()"

Using a single object (not an array) works elsewhere in the application. It's when I try to use an array that things don't compile. What is the difference between a standalone signal and an input signal in this situation?

2 Answers 2

2

You are missing to initialize the signal with accounts = input.required<any[]>().

import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';

import { computed, input } from '@angular/core';

@Component({
  selector: 'app-child',
  standalone: true,
  imports: [],
  template: `
  @for (account of accounts(); track account.name) {
    <div>{{account.name}}</div>
  }
  <div>Total: {{totalLiquidationValue()}}</div>
  `
})
export class ChildComponent {
  accounts = input.required<any[]>();
  totalLiquidationValue = computed(() => {
    return this.accounts().reduce(
      (a: any, acct: any) => (a += acct.liquidationValue),
      0
    );
  });
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ChildComponent],
  template: `
    <app-child [accounts]="accounts"/>
  `,
})
export class App {
  accounts = [
    { name: 'test', liquidationValue: 1 },
    { name: 'test2', liquidationValue: 2 },
    { name: 'test3', liquidationValue: 3 },
  ];
}

bootstrapApplication(App);

Stackblitz Demo

Sign up to request clarification or add additional context in comments.

Comments

2

Your code doesn't invoke the required function.

accounts = input.required<Account[]>;

It should have been

accounts = input.required<Account[]>();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.