(publicName: string, value: WritableSignal<unknown>)
| 217 | * @see [Binding inputs, outputs and setting host directives at creation](guide/components/programmatic-rendering#binding-inputs-outputs-and-setting-host-directives-at-creation) |
| 218 | */ |
| 219 | export function twoWayBinding(publicName: string, value: WritableSignal<unknown>): Binding { |
| 220 | const input = inputBinding(publicName, value) as BindingInternal; |
| 221 | const output = outputBinding(publicName + 'Change', (eventValue) => |
| 222 | value.set(eventValue), |
| 223 | ) as BindingInternal; |
| 224 | |
| 225 | // We take advantage of inputs only having a `create` block and outputs only having an `update` |
| 226 | // block by passing them through directly instead of creating dedicated functions here. This |
| 227 | // assumption can break down if one of them starts targeting both blocks. These assertions |
| 228 | // are here to help us catch it if something changes in the future. |
| 229 | ngDevMode && assertNotDefined(input.create, 'Unexpected `create` callback in inputBinding'); |
| 230 | ngDevMode && assertNotDefined(output.update, 'Unexpected `update` callback in outputBinding'); |
| 231 | |
| 232 | const binding: BindingInternal = { |
| 233 | [BINDING]: { |
| 234 | kind: 'twoWay', |
| 235 | requiredVars: input[BINDING].requiredVars + output[BINDING].requiredVars, |
| 236 | }, |
| 237 | set targetIdx(idx: number) { |
| 238 | (input as Writable<BindingInternal>).targetIdx = idx; |
| 239 | (output as Writable<BindingInternal>).targetIdx = idx; |
| 240 | }, |
| 241 | create: output.create, |
| 242 | update: input.update, |
| 243 | }; |
| 244 | return binding; |
| 245 | } |
no test coverage detected
searching dependent graphs…