| 575 | } |
| 576 | |
| 577 | override setInput(name: string, value: unknown): void { |
| 578 | if (this._hasInputBindings && ngDevMode) { |
| 579 | throw new RuntimeError( |
| 580 | RuntimeErrorCode.INVALID_SET_INPUT_CALL, |
| 581 | 'Cannot call `setInput` on a component that is using the `inputBinding` or `twoWayBinding` functions.', |
| 582 | ); |
| 583 | } |
| 584 | |
| 585 | const tNode = this._tNode; |
| 586 | this.previousInputValues ??= new Map(); |
| 587 | // Do not set the input if it is the same as the last value |
| 588 | // This behavior matches `bindingUpdated` when binding inputs in templates. |
| 589 | if ( |
| 590 | this.previousInputValues.has(name) && |
| 591 | Object.is(this.previousInputValues.get(name), value) |
| 592 | ) { |
| 593 | return; |
| 594 | } |
| 595 | |
| 596 | const lView = this._rootLView; |
| 597 | const hasSetInput = setAllInputsForProperty(tNode, lView[TVIEW], lView, name, value); |
| 598 | this.previousInputValues.set(name, value); |
| 599 | const childComponentLView = getComponentLViewByIndex(tNode.index, lView); |
| 600 | markViewDirty(childComponentLView, NotificationSource.SetInput); |
| 601 | |
| 602 | if (ngDevMode && !hasSetInput) { |
| 603 | const cmpNameForError = stringifyForError(this.componentType); |
| 604 | let message = `Can't set value of the '${name}' input on the '${cmpNameForError}' component. `; |
| 605 | message += `Make sure that the '${name}' property is declared as an input using the input() or model() function or the @Input() decorator.`; |
| 606 | reportUnknownPropertyError(message); |
| 607 | } |
| 608 | } |
| 609 | |
| 610 | override get injector(): Injector { |
| 611 | return new NodeInjector(this._tNode, this._rootLView); |