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