DEV Community

Cover image for Making a Read-Only Signal Editable in Your Component
Kobi Hari
Kobi Hari

Posted on

Making a Read-Only Signal Editable in Your Component

Sometimes you inject a signal from a service, and it’s read-only, but you still want the user to edit it inside your component.

@Component({
  selector: 'user-editor',
  template: `
    <input [(ngModel)]="?">
  `
})
export class UserEditor {
    readonly user = inject(UserService).userSignal; // Signal<User>
    readonly username = computed(() => this.user().name); // Signal<string>

}
Enter fullscreen mode Exit fullscreen mode

How do you make that happen without breaking immutability?

That’s where linkedSignal() comes in.

Linked Signal to the rescue

Linked Signal creates a local writable signal that stays in sync with the original one, so you can use it for two-way binding with the familiar banana-in-a-box syntax [(model)].

@Component({
  selector: 'user-editor',
  template: `
    <input [(ngModel)]="editableUsername">
  `
})
export class UserEditor {
    readonly user = inject(UserService).userSignal; // Signal<User>
    readonly username = computed(() => this.user().name); // Signal<string>
    readonly editableUsername = linkedSignal(() => this.username());
}
Enter fullscreen mode Exit fullscreen mode
  • Keeps your parent state immutable
  • Allows local edits in the child
  • Feels natural for Angular developers

That’s the beauty of linkedSignal. It bridges Angular’s modern signal world with the old-school simplicity of banana-in-a-box syntax.

Value Source

Now the linked signal may hold a value that’s either coming from the service or modified locally by the user.
But how do you tell which one it is?

You can use a computed signal to compare the original value with the current value of the linked signal:

readonly valueSource = computed(() => 
    this.username() === this.editableUsername()
        ? 'remote'
        : 'local');
Enter fullscreen mode Exit fullscreen mode

The valueSourcesignal now tells you whether the current value is local (changed by the user) or remote (still matches the service).


If you found this useful, follow me for more posts about Angular Signals, NgRx Signal Store, and building scalable Angular apps.

Top comments (0)