Skip to content

Signal Forms: Enable safe side-effects or payload access from async validators (cannot write to signals inside onSuccess) #66405

@okeydoky

Description

@okeydoky

Which @angular/* package(s) are relevant/related to the feature request?

forms

Description

Not really a feature request, but a brainstorming how to handle this scenario using signal forms.

Some backends return domain payloads along with validation results (for example, a User object when a userId is valid). With signal-forms, attempting to persist that payload by writing to another signal inside the validator’s onSuccess leads to NG0600: Writing to signals is not allowed in a computed. It would be helpful to have a supported pattern or API to consume/store such payloads without violating the “no writes in computed” rule.

Use case

  • A form field accepts a userId.
  • An async validator checks validity.
  • If valid, the endpoint also returns the User object.
  • The app should display full user details without issuing a second request.

Repro snippet

validateHttp<string, UserValidationResponse>(f.userId, { 
  request: ({ value }) => /example-api/user-info?id=${value()}, 
  onSuccess: (resp) => { 
    if (resp.result === 'invalid') { 
      return customError({ kind: 'invalid id', message: 'Invalid user id', });
     } 
    // Persist the user for later UI use 
    this.user.set(resp.user); // throws NG0600 
    return undefined; 
  }, 
  onError: () => customError({ kind: 'bad request', message: 'Bad Request' }), 
});

Actual behavior

Error: NG0600: Writing to signals is not allowed in a computed (onSuccess executes within a computed context, so setting this.user fails).

Proposed solution

A first-class, documented way to:

  • Safely persist or expose the payload returned by the async validator, and/or
  • Perform side-effects (like setting another signal) after the validator settles, outside computed evaluation.

Why this matters

  • Avoids redundant network calls (don’t fetch user details twice).
  • Reduces latency and improves UX.
  • Mirrors common backend patterns where validation returns enriched data.

Alternatives considered

Some ideas:

  1. Side-effect callback outside computed

Add an option like onResolved or onSettled that runs after the validator’s computed completes, allowing safe writes to signals:
onResolved: ({ response, error }) => { if (response?.user) user.set(response.user); }

  1. validateHttp to returns something?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions