क्या है AngDefaultControl कोणीय में?


104

नहीं, यह कोई डुप्लिकेट प्रश्न नहीं है। आप देखते हैं, एसओ और जीथब में कुछ सवाल और मुद्दे हैं जो यह बताते हैं कि मैं इस निर्देश को एक टैग में जोड़ता हूं जिसमें [(ngModel)]निर्देश है और जो किसी रूप में निहित नहीं है। अगर मैं इसे नहीं जोड़ता तो मुझे एक त्रुटि मिलती है:

ERROR Error: No value accessor for form control with unspecified name attribute

ठीक है, अगर मैं इस विशेषता को वहां रखूं तो त्रुटि दूर हो जाती है। लेकिन रुकें! कोई नहीं जानता कि यह क्या करता है! और एंगुलर के डॉक में इसका जिक्र नहीं है। जब मुझे पता है कि मुझे इसकी आवश्यकता नहीं है तो मुझे मूल्य अभिगमकर्ता की आवश्यकता क्यों है? यह विशेषता मान एक्सेसर्स से कैसे जुड़ी है? यह निर्देश क्या करता है? मूल्य अभिगमकर्ता क्या है और मैं इसका उपयोग कैसे करूं?

और हर कोई उन चीजों को क्यों करता रहता है जो उन्हें समझ में नहीं आती हैं? बस इस कोड को जोड़ें और यह काम करता है, धन्यवाद, यह अच्छा कार्यक्रम लिखने का तरीका नहीं है।

और तब। मैं कोणीय में रूपों के बारे में एक नहीं बल्कि दो विशाल गाइडों को पढ़ता हूं और एक अनुभाग ngModel:

और क्या आपको पता है? वैल्यू एक्सेसर्स या दोनों का एक भी उल्लेख नहीं है ngDefaultControl। कहाँ है?


> "और हर कोई उन चीजों को क्यों करता रहता है जिन्हें वे बिल्कुल नहीं समझते हैं?" - हाँ! बिल्कुल सही! यह कुछ और विस्मय बोधक बिंदुओं का उपयोग कर सकता है; हालांकि ;-)
Guss

जवाबों:


181

[NgDefaultControl]

तृतीय पक्ष नियंत्रण ControlValueAccessorको कोणीय रूपों के साथ कार्य करने की आवश्यकता होती है । पॉलिमर की तरह उनमें से कई <paper-input>, <input>मूल तत्व की तरह व्यवहार करते हैं और इस प्रकार उपयोग कर सकते हैं DefaultValueAccessor। एक ngDefaultControlविशेषता जोड़ने से वे उस निर्देश का उपयोग कर सकेंगे।

<paper-input ngDefaultControl [(ngModel)]="value>

या

<paper-input ngDefaultControl formControlName="name">

इसलिए यह मुख्य कारण है कि इस पोशाक को पेश किया गया था।

इसे कोणीय 2 के अल्फा संस्करणों मेंng-default-control विशेषता कहा जाता था ।

तो DefaultValueAccessor निर्देश के ngDefaultControlलिए चयनकर्ताओं में से एक है :

@Directive({
  selector:
      'input:not([type=checkbox])[formControlName],
       textarea[formControlName],
       input:not([type=checkbox])[formControl],
       textarea[formControl],
       input:not([type=checkbox])[ngModel],
       textarea[ngModel],
       [ngDefaultControl]', <------------------------------- this selector
  ...
})
export class DefaultValueAccessor implements ControlValueAccessor {

इसका क्या मतलब है?

इसका अर्थ है कि हम इस विशेषता को तत्व (बहुलक घटक की तरह) लागू कर सकते हैं, जिसका अपना मूल्य अभिगमकर्ता नहीं है। इसलिए यह तत्व व्यवहार करेगा DefaultValueAccessorऔर हम इस तत्व को कोणीय रूपों के साथ उपयोग कर सकते हैं।

अन्यथा आपको अपना स्वयं का कार्यान्वयन प्रदान करना होगा ControlValueAccessor

ControlValueAccessor

कोणीय डॉक्स राज्यों

एक ControlValueAccessor कोणीय रूपों API और DOM में एक मूल तत्व के बीच एक सेतु का काम करता है।

आइए, सरल कोणीय 2 अनुप्रयोग में निम्नलिखित टेम्पलेट लिखें:

<input type="text" [(ngModel)]="userName">

यह समझने के लिए कि हमारा inputउपरोक्त व्यवहार कैसे होगा, हमें यह जानना होगा कि इस तत्व पर कौन से निर्देश लागू किए गए हैं। यहाँ कोणीय त्रुटि के साथ कुछ संकेत देता है:

अनहेल्दीड प्रॉमिस रिजेक्शन: टेम्प्लेट पार्स एरर्स: 'एनमॉडेल' से बंध नहीं सकते क्योंकि यह 'इनपुट' की ज्ञात संपत्ति नहीं है।

ठीक है, हम एसओ खोल सकते हैं और जवाब पा FormsModuleसकते हैं @NgModule: आपके लिए आयात :

@NgModule({
  imports: [
    ...,
    FormsModule
  ]
})
export AppModule {}

हमने इसे आयात किया है और सभी इरादा के अनुसार काम करते हैं। लेकिन हुड के नीचे क्या हो रहा है?

निम्नलिखित निर्देशों के लिए हमारे लिए FormModule निर्यात:

@NgModule({
 ...
  exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]
})
export class FormsModule {}

यहां छवि विवरण दर्ज करें

कुछ जांच के बाद हमें पता चलता है कि हमारे लिए तीन निर्देश लागू होंगे input

1) NgControlStatus

@Directive({
  selector: '[formControlName],[ngModel],[formControl]',
  ...
})
export class NgControlStatus extends AbstractControlStatus {
  ...
}

2) एनजीमॉडल

@Directive({
  selector: '[ngModel]:not([formControlName]):not([formControl])',
  providers: [formControlBinding],
  exportAs: 'ngModel'
})
export class NgModel extends NgControl implements OnChanges, 

3) DEFAULT_VALUE_ACCESSOR

@Directive({
  selector:
      `input:not([type=checkbox])[formControlName],
       textarea[formControlName],
       input:not([type=checkbox])formControl],
       textarea[formControl],
       input:not([type=checkbox])[ngModel],
       textarea[ngModel],[ngDefaultControl]',
  ,,,
})
export class DefaultValueAccessor implements ControlValueAccessor {

NgControlStatusनिर्देश सिर्फ manipulates वर्गों की तरह ng-valid, ng-touched, ng-dirtyऔर हम उसे यहां छोड़ सकते हैं।


DefaultValueAccesstorNG_VALUE_ACCESSORप्रदाताओं में टोकन प्रदान करता है सरणी:

export const DEFAULT_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => DefaultValueAccessor),
  multi: true
};
...
@Directive({
  ...
  providers: [DEFAULT_VALUE_ACCESSOR]
})
export class DefaultValueAccessor implements ControlValueAccessor {

NgModelNG_VALUE_ACCESSORएक ही होस्ट तत्व पर घोषित किए गए निर्माता टोकन में निर्देश इंजेक्ट करता है।

export NgModel extends NgControl implements OnChanges, OnDestroy {
 constructor(...
  @Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: ControlValueAccessor[]) {

हमारे मामले NgModelमें इंजेक्शन होगा DefaultValueAccessor। और अब NgModel निर्देश कॉल साझा setUpControlसमारोह:

export function setUpControl(control: FormControl, dir: NgControl): void {
  if (!control) _throwError(dir, 'Cannot find control with');
  if (!dir.valueAccessor) _throwError(dir, 'No value accessor for form control with');

  control.validator = Validators.compose([control.validator !, dir.validator]);
  control.asyncValidator = Validators.composeAsync([control.asyncValidator !, dir.asyncValidator]);
  dir.valueAccessor !.writeValue(control.value);

  setUpViewChangePipeline(control, dir);
  setUpModelChangePipeline(control, dir);

  ...
}

function setUpViewChangePipeline(control: FormControl, dir: NgControl): void 
{
  dir.valueAccessor !.registerOnChange((newValue: any) => {
    control._pendingValue = newValue;
    control._pendingDirty = true;

    if (control.updateOn === 'change') updateControl(control, dir);
  });
}

function setUpModelChangePipeline(control: FormControl, dir: NgControl): void {
  control.registerOnChange((newValue: any, emitModelEvent: boolean) => {
    // control -> view
    dir.valueAccessor !.writeValue(newValue);

    // control -> ngModel
    if (emitModelEvent) dir.viewToModelUpdate(newValue);
  });
}

और यहाँ कार्रवाई में पुल है:

यहां छवि विवरण दर्ज करें

NgModelनियंत्रण (1) और कॉल dir.valueAccessor !.registerOnChangeविधि सेट करता है। (2) प्रॉपर्टी ControlValueAccessorमें कॉलबैक स्टोर करता है और इवेंट (3) होने पर यह कॉलबैक फायर करता है । और अंत में फ़ंक्शन कॉलबैक (4) के अंदर कॉल किया जाता हैonChangeinputupdateControl

function updateControl(control: FormControl, dir: NgControl): void {
  dir.viewToModelUpdate(control._pendingValue);
  if (control._pendingDirty) control.markAsDirty();
  control.setValue(control._pendingValue, {emitModelToViewChange: false});
}

जहां कोणीय कॉल एपीआई बनाता है control.setValue

यह कैसे काम करता है इसका एक छोटा संस्करण है।


मैंने बस बनाया @Input() ngModelऔर @Output() ngModelChangeद्विदिश बाध्यकारी के लिए और मैंने सोचा कि यह एक पुल होना चाहिए। यह एक ही तरह से पूरी तरह से अलग काम करता है। शायद मुझे अपने क्षेत्र का नाम नहीं देना चाहिए ngModel?
घुमारवीं

3
यदि आप इस घटक को कोणीय रूपों के साथ उपयोग नहीं करते हैं, तो आप बस अपना खुद का दो-तरफ़ा बंधन बना सकते हैं जैसे @Input() value; @Output() valueChange: EventEmitter<any> = new EventEmitter();और फिर उपयोग कर सकते हैं[(value)]="someProp"
yurzui

2
ठीक यही मैं कर रहा था। लेकिन मैंने अपने "मूल्य" को नाम ngModelदिया और एंगुलर ने मुझ पर एक त्रुटि फेंकना शुरू कर दिया और ControlValueAccessor के साथ पूछना शुरू कर दिया।
घुमारवीं

क्या कोई है जो vue और React में ngDefaultControl के बराबर है? मेरा मतलब है, मैंने नियंत्रण मूल्य अभिगमक का उपयोग करके कोणीय में एक कस्टम इनपुट घटक बनाया और इसे कोणीय तत्वों में एक वेब घटक के रूप में लपेटा। उसी परियोजना में मुझे कोणीय रूपों के साथ काम करने के लिए ngDefaultControl का उपयोग करना पड़ा। लेकिन मुझे उन्हें Vue और React में काम करने के लिए क्या करना चाहिए? देशी जेएस में भी?
कविन्द्र जयकौड़ी

मैं अपने कस्टम घटक पर ngDefaultControl का उपयोग कर रहा हूं लेकिन मैं एक समस्या से जूझ रहा हूं। जब मैं अपने फॉर्म के अंदर फॉर्मल कंटोल के लिए डिफ़ॉल्ट मान सेट करता हूं तो बाउबल व्यू (कस्टम इनपुट कंपोनेंट) अपडेट नहीं होता है, केवल मॉडल। मैं क्या गलत कर रहा हूं?
इगोर जानकोविले
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.