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
idto 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
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.