Which @angular/* package(s) are the source of the bug?
forms
Is this a regression?
No
Description
I discovered this while trying to find a good solution how to edit a list of users with signal forms, which actually does not sound complicated, but it seems that there are things to consider I might not yet be aware of. Please see https://stackoverflow.com/questions/79878016/angular-21-signal-forms-how-to-loop-over-an-array-of-complex-sub-objects for the whole story.
In the 3rd example I described there, I tried to add a id to each user and use this for tracking in the loop like this. (StackBlitz Example 3)
interface User { id: number; name?: string; }
interface UserForm { id: number; name: string; }
interface Test { test: string; users: User[]; }
let userCounter = 0;
function createUser(name?: string): User { return { id: ++userCounter, name }; }
@Component({
selector: 'user-edit',
template: `<div>Name: <input type="text" [formField]="valueForm.name"/></div>`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [FormField],
})
export class UserEditComponent implements FormValueControl<User | null> {
public readonly value = model<User | null>(null);
protected readonly valueForm = mappedForm<User | null, UserForm>(this.value, {
modelToForm: (user) => {
user ??= createUser('new user');
return { id: user.id, name: user.name ?? '(unnamed))' };
},
formToModel: (userForm) => ({ id: userForm.id,name: userForm.name || undefined, }),
});
}
@Component({
selector: 'app-root',
template: `
<!-- instead of $index use form's user ID for tracking -->
@for(userForm of valueForm.users; track userForm.id().value()) {
<p>{{ userForm().value() | json }}</p>
<user-edit [formField]="userForm" />
}
<button (click)="addUser()">Add User</button>
`,
imports: [UserEditComponent, FormField, JsonPipe],
})
export class App {
public readonly value = signal<Test>({ test: 'a', users: [createUser('a'), createUser('b')], });
public readonly valueForm = form(this.value);
addUser() {
this.valueForm
.users()
.value.update((list) => [...list, createUser(`user ${list.length}`)]);
}
}
I expected that this improved tracking, but instead I get a runtime error and adding or editing users does not work.
Please provide a link to a minimal reproduction of the bug
https://stackblitz.com/edit/stackblitz-starters-3r7vqbdb?file=src%2Fmain.ts,src%2Fuser-edit.component.ts
Please provide the exception or error you saw
ERROR RuntimeError: NG01904: Orphan field, can't find element in array <root>.users
at Object.computation (_structure-chunk.mjs:953:15)
at Object.producerRecomputeValue (_effect-chunk.mjs:310:25)
at producerUpdateValueVersion (_effect-chunk.mjs:102:8)
at computed2 (_effect-chunk.mjs:271:5)
at Object.computation (_structure-chunk.mjs:850:40)
at Object.producerRecomputeValue (_effect-chunk.mjs:310:25)
at producerUpdateValueVersion (_effect-chunk.mjs:102:8)
at consumerPollProducersForChange (_effect-chunk.mjs:170:5)
at producerUpdateValueVersion (_effect-chunk.mjs:98:45)
at linkedSignalGetter (_linked_signal-chunk.mjs:17:5)
Please provide the environment you discovered this bug in (run ng version)
Angular CLI : 21.1.1
Angular : 21.1.1
Node.js : 20.19.1
Package Manager : pnpm 8.15.6
Operating System : linux x64
┌───────────────────────────┬───────────────────┬───────────────────┐
│ Package │ Installed Version │ Requested Version │
├───────────────────────────┼───────────────────┼───────────────────┤
│ @angular/animations │ 21.1.1 │ 21.1.1 │
│ @angular/build │ 21.1.1 │ 21.1.1 │
│ @angular/cli │ 21.1.1 │ 21.1.1 │
│ @angular/common │ 21.1.1 │ 21.1.1 │
│ @angular/compiler │ 21.1.1 │ 21.1.1 │
│ @angular/compiler-cli │ 21.1.1 │ 21.1.1 │
│ @angular/core │ 21.1.1 │ 21.1.1 │
│ @angular/forms │ 21.1.1 │ 21.1.1 │
│ @angular/platform-browser │ 21.1.1 │ 21.1.1 │
│ @angular/router │ 21.1.1 │ 21.1.1 │
│ rxjs │ 7.8.2 │ ^7.8.1 │
│ typescript │ 5.9.3 │ ^5.9.3 │
└───────────────────────────┴───────────────────┴───────────────────┘
Anything else?
Maybe the docs part about signal forms working with arrays could be enhanced a little bit to give also examples for this case.
Which @angular/* package(s) are the source of the bug?
forms
Is this a regression?
No
Description
I discovered this while trying to find a good solution how to edit a list of users with signal forms, which actually does not sound complicated, but it seems that there are things to consider I might not yet be aware of. Please see https://stackoverflow.com/questions/79878016/angular-21-signal-forms-how-to-loop-over-an-array-of-complex-sub-objects for the whole story.
In the 3rd example I described there, I tried to add a id to each user and use this for tracking in the loop like this. (StackBlitz Example 3)
I expected that this improved tracking, but instead I get a runtime error and adding or editing users does not work.
Please provide a link to a minimal reproduction of the bug
https://stackblitz.com/edit/stackblitz-starters-3r7vqbdb?file=src%2Fmain.ts,src%2Fuser-edit.component.ts
Please provide the exception or error you saw
ERROR RuntimeError: NG01904: Orphan field, can't find element in array <root>.users at Object.computation (_structure-chunk.mjs:953:15) at Object.producerRecomputeValue (_effect-chunk.mjs:310:25) at producerUpdateValueVersion (_effect-chunk.mjs:102:8) at computed2 (_effect-chunk.mjs:271:5) at Object.computation (_structure-chunk.mjs:850:40) at Object.producerRecomputeValue (_effect-chunk.mjs:310:25) at producerUpdateValueVersion (_effect-chunk.mjs:102:8) at consumerPollProducersForChange (_effect-chunk.mjs:170:5) at producerUpdateValueVersion (_effect-chunk.mjs:98:45) at linkedSignalGetter (_linked_signal-chunk.mjs:17:5)Please provide the environment you discovered this bug in (run ng version)
Anything else?
Maybe the docs part about signal forms working with arrays could be enhanced a little bit to give also examples for this case.