@@ -11,8 +11,9 @@ import {RuntimeError, RuntimeErrorCode} from '../errors';
1111import { Type , Writable } from '../interface/type' ;
1212import { assertNotDefined } from '../util/assert' ;
1313import { bindingUpdated } from './bindings' ;
14- import { ɵɵcontrolCreate as controlCreate , updateControl } from './instructions/control' ;
1514import { setDirectiveInput , storePropertyBindingMetadata } from './instructions/shared' ;
15+ import { ɵCONTROL } from './interfaces/control' ;
16+ import { TNode } from './interfaces/node' ;
1617import { TVIEW } from './interfaces/view' ;
1718import { getCurrentTNode , getLView , getSelectedTNode , nextBindingIndex } from './state' ;
1819import { stringifyForError } from './util/stringify_utils' ;
@@ -102,6 +103,23 @@ function inputBindingUpdate(targetDirectiveIdx: number, publicName: string, valu
102103 }
103104}
104105
106+ /**
107+ * Instructions for dynamically binding a `Field` to a form control.
108+ */
109+ interface ControlBinding {
110+ create : ( ) => void ;
111+ update : ( ) => void ;
112+ }
113+
114+ /**
115+ * Returns a {@link ControlBinding} for the target directive if it is a 'Field' directive.
116+ */
117+ function controlBinding ( binding : BindingInternal , tNode : TNode ) : ControlBinding | undefined {
118+ const lView = getLView ( ) ;
119+ const directive = lView [ tNode . directiveStart + binding . targetIdx ! ] ;
120+ return directive [ ɵCONTROL ] ;
121+ }
122+
105123/**
106124 * Creates an input binding.
107125 * @param publicName Public name of the input to bind to.
@@ -125,15 +143,16 @@ export function inputBinding(publicName: string, value: () => unknown): Binding
125143 if ( publicName === 'field' ) {
126144 const binding : BindingInternal = {
127145 [ BINDING ] : FIELD_BINDING_METADATA ,
128- create : ( ) => controlCreate ( ) ,
146+ create : ( ) => {
147+ // Set up the form control bindings, if this is a 'Field' directive bound to a form control.
148+ controlBinding ( binding , getCurrentTNode ( ) ! ) ?. create ( ) ;
149+ } ,
129150 update : ( ) => {
130- // Update the [field] input binding.
131- inputBindingUpdate ( ( binding as BindingInternal ) . targetIdx ! , publicName , value ( ) ) ;
151+ // Update the [field] input binding, regardless of whether this targets a 'Field' directive .
152+ inputBindingUpdate ( binding . targetIdx ! , publicName , value ( ) ) ;
132153
133154 // Update the form control bindings, if this is a 'Field' directive bound to a form control.
134- const lView = getLView ( ) ;
135- const tNode = getSelectedTNode ( ) ;
136- updateControl ( lView , tNode ) ;
155+ controlBinding ( binding , getSelectedTNode ( ) ! ) ?. update ( ) ;
137156 } ,
138157 } ;
139158 return binding ;
@@ -143,7 +162,7 @@ export function inputBinding(publicName: string, value: () => unknown): Binding
143162 // don't get tree shaken when constructed by a function like this.
144163 const binding : BindingInternal = {
145164 [ BINDING ] : INPUT_BINDING_METADATA ,
146- update : ( ) => inputBindingUpdate ( ( binding as BindingInternal ) . targetIdx ! , publicName , value ( ) ) ,
165+ update : ( ) => inputBindingUpdate ( binding . targetIdx ! , publicName , value ( ) ) ,
147166 } ;
148167
149168 return binding ;
0 commit comments