# A callback that answers

> A component's callback parameter may return a value. Typed `Func<T, R>` and invoked from an action, it runs the parent's handler to completion and answers what the handler returned — and an exception the handler throws reaches the component at that call, where its own `try` catches it.

<!-- id: ui-callback-value · area: ui · stability: preview · html: https://osysharp.com/reference/ui/callback-value/ -->

## Summary        {#summary}
A reusable component often needs its parent to *do* something and tell it how that went: make the record, save the
draft, check the name. Declare the callback as a `Func` that returns what the parent makes, and call it from an action:

```osy title="the child gets the parent's value, and catches the parent's refusal" test app=ui-callback-value
app Notes {
  model "model/**/*.osy";
  use Osysharp.Ui;
}

entity Note {
  [Required, MaxLength(80)] string Title;
  security { allow read, create when IsAnonymous || IsAuthenticated; }
}

[Composable] component Adder(Func<string, Note> add) {
  string title = "";
  string error = "";
  string made = "";
  action Save() {
    try {
      var note = add(title);          // runs the parent's handler, and waits for it
      made = "Made " + note.Title;
    } catch (ValidationException ex) {
      error = ex.Message;             // the parent's own words
    }
  }
  render {
    Stack(gap: 2) {
      Input(value: title);
      Button("Save", onPress: Save);
      Text(made);
      Text(error);
    }
  }
}

[Route("/")] [AllowAnonymous]
component Home() {
  Note Make(string t) {
    if (t == "") { throw new ValidationException("Name it."); }
    var note = new Note { Title = t };
    UnitOfWork.Commit();               // the act IS the save — without it the note is never stored
    return note;
  }
  render { Adder(add: Make); }
}
```

## Signature      {#signature}
```osy syntax
component C(Func<T, R> handle)        // a callback that answers an R
handle(value)                         // in an action: waits for the parent, answers its R

C(handle: ParentMethod)               // the parent passes a method that returns an R
R ParentMethod(T value) { … }
```

## Description    {#description}

### It waits — with or without `await`   {#waits}
A call that has to wait simply suspends where it is and resumes with the answer, so `Func<T, R>` called like any
function is enough: the action pauses at the call until the parent's handler has finished, then carries on with its
value. C#'s own spelling — a `Func<T, Task<R>>` the component `await`s, and an `async Task<R>` method in the parent —
means the same thing and works as written ([async / await and Task](https://osysharp.com/reference/function/async-await/)):

```osy title="the C# spelling: Task<R> in the callback type, await at the call" test app=ui-callback-value-task
app Notes {
  model "model/**/*.osy";
  use Osysharp.Ui;
}

entity Note {
  [Required, MaxLength(80)] string Title;
  security { allow read, create when IsAnonymous || IsAuthenticated; }
}

[Composable] component Adder(Func<string, Task<Note>> add) {
  string title = "";
  string made = "";
  action Save() {
    var note = await add(title);
    made = "Made " + note.Title;
  }
  render {
    Stack(gap: 2) {
      Field("Title", value: title);
      Button("Save", onPress: Save);
      Text(made);
    }
  }
}

[Route("/")] [AllowAnonymous]
component Home() {
  async Task<Note> Make(string t) {
    var note = new Note { Title = t };
    UnitOfWork.Commit();
    return note;
  }
  render { Adder(add: Make); }
}
```

### The parent's exception is the component's to catch   {#faults}
If the parent's handler throws — a rule the component knows nothing about, a name that is taken — the exception is
raised **at the call** in the component's action. A `try` around the call catches it, which is how a dialog stays
open and shows the parent's reason instead of closing on something that was never made. Uncaught, it fails the
component's action exactly as an exception of its own would.

### What the parent passes   {#binding}
The parent names a **method** of its own that returns the answer — `add: Make`, as an event handler is passed by
name. The method may do anything an action may: create rows, read data, call a server function. A parent may also pass
a lambda (`add: t => new Note { Title = t }`); a lambda is an expression, so it answers at once.

### `Action` is the callback that answers nothing   {#action}
A void `Action<T>` callback is fired and the component carries on without waiting: nothing comes back, so there is
nothing to wait for. When the component needs to know how it went — a value, or that it was refused — declare a
`Func`.

### One action at a time, still   {#one-at-a-time}
A page runs its actions one at a time. The parent's handler runs *inside* the waiting action rather than after it, so
it sees the same unsaved changes the action made, and its own changes are kept with them until the page saves.

## Examples       {#examples}
```osy title="a settings section that hands the parent a draft and gets back the field it made" syntax
[Composable] component FieldList(CustomField[] fields, Func<FieldDraft, CustomField> add) {
  string addError = "";
  action Add(FieldDraft draft) {
    try { var made = add(draft); }
    catch (Exception ex) { addError = ex.Message; }
  }
}

// the parent:
CustomField AddGuestField(FieldDraft d) => FillField(new GuestField(), d, fields.Count);
// …
FieldList(fields, AddGuestField);
```

## See also       {#see-also}
- [component](https://osysharp.com/reference/ui/component/) — parameters, state and actions
- [Func<T, R>](https://osysharp.com/reference/ui/function-value/) — a `Func` used for a value in a render expression: a selector, a formatter
- [async / await and Task](https://osysharp.com/reference/function/async-await/) — `async`, `await` and `Task`
- [try / catch / finally](https://osysharp.com/reference/function/try-catch/) — catching a fault by its type
