2016-04-23 2 views
6

में इनपुट तत्व परिवर्तनों का निरीक्षण कैसे करें जब बच्चे घटक इनपुट इनपुट में परिवर्तन करते हैं तो पैरेंट घटक के फ़ंक्शन को कैसे कॉल करें?एनजी-सामग्री

नीचे HTML संरचना है।

# app.comopnent.html 
<form> 
    <textbox> 
    <input type="text"> 
    </textbox> 
</form> 

# textbox.component.html 
<div class="textbox-wrapper"> 
    <ng-content> 
</div> 

प्रतिबंध निम्नानुसार हैं।

  • TextboxComponent ng-content है और यह करने के लिए input तत्व पेश करने की जरूरत है।
  • input तत्व को इनपुट किया गया है जब टेक्स्टबॉक्सकंपोनेंट में एक ईवेंट उत्सर्जित करें।
  • input तत्व को अधिक विशेषताओं के लिए बनाना नहीं चाहते हैं, उदा। <input type="text" (input)="event()">

मैं कोड लिख रहा था, लेकिन एक समाधान नहीं मिल सकता है ...

# input.directive.ts 
@Directive({ selector: 'input', ... }) 
export class InputDirective { 
    ngOnChanges(): void { 
    // ngOnChanges() can observe only properties defined from @Input Decorator... 
    } 
} 

# textbox.component.ts 
@Component({ selector: 'textbox', ... }) 
export class TextboxComponent { 
    @ContentChildren(InputDirective) inputs: QueryList<InputDirective>; 
    ngAfterContentInit(): void { 
    this.inputs.changes.subscribe((): void => { 
     // QueryList has a changes property, it can observe changes when the component add/remove. 
     // But cannot observe input changes... 
    }); 
    } 
} 
+0

क्यों नहीं करते आप एक निर्गम का उपयोग करना चाहते बाध्यकारी, जैसे <इनपुट प्रकार = "पाठ" (इनपुट) = "घटना()">? आप कैसे सुनिश्चित कर सकते हैं कि अन्य devs (या यहां तक ​​कि आप) केवल टेक्स्टबॉक्स कॉम्पोनेंट के मार्कअप में इनपुट तत्व जोड़ते हैं? – rrjohnson85

+0

क्योंकि मुझे 'इनपुट' तत्व को बाध्यकारी आउटपुट जोड़ना चाहिए और यदि मैं इसका उपयोग करना चाहता हूं तो यह वर्बोज़ है। लेकिन मैं बजाय 'होस्ट: {(इनपुट):' event() '}' संपत्ति का उपयोग इनपुट डायरेक्टिव में कर सकता हूं। सबसे बड़ी समस्या यह है कि टेक्स्टबॉक्सकंपेंटेंट 'एनजी-कंटेंट' का उपयोग कर पता लगा सकता है जब इनपुट डायरेक्टिव को कुछ भी इनपुट किया गया था। –

उत्तर

5

input घटना बुदबुदाती है और माता पिता के घटक

<div class="textbox-wrapper" (input)="inputChanged($event)"> 
    <ng-content></ng-content> 
</div> 

Plunker example

+0

ओह! मुझे यह नहीं पता था ... मैं व्यवहार की उम्मीद कर सकता था !! धन्यवाद!! –

1

आप इस परिदृश्य है, जो इनपुट निर्देश

input.directive.ts पर संपत्ति hostbinding है इस्तेमाल कर सकते हैं

import {Directive, HostBinding} from 'angular2/core'; 
import {Observer} from 'rxjs/Observer'; 
import {Observable} from 'rxjs/Observable'; 

@Directive({ 
    selector: 'input', 
    host: {'(input)': 'onInput($event)'} 
}) 
export class InputDirective { 
    inputChange$: Observable<string>; 
    private _observer: Observer<any>; 
    constructor() { 
    this.inputChange$ = new Observable(observer => this._observer = observer); 
    } 
    onInput(event) { 
    this._observer.next(event.target.value); 
    } 
} 

और फिर अपने TextBoxComponent नमूदार पर सदस्यता होगा ऑब्जेक्ट डायरेक्टिव क्लास में ऊपर परिभाषित ऑब्जेक्ट।

textbox.component.ts

import {Component, ContentChildren,QueryList} from 'angular2/core'; 
import {InputDirective} from './input.directive'; 
@Component({ 
    selector: 'textbox', 
    template: ` 
    <div class="textbox-wrapper"> 
     <ng-content></ng-content> 
     <div *ngFor="#change of changes"> 
     {{change}} 
     </div> 
    </div> 
    ` 
}) 
export class TextboxComponent { 
    private changes: Array<string> = []; 
    @ContentChildren(InputDirective) inputs: QueryList<InputDirective>; 

    onChange(value, index) { 
    this.changes.push(`input${index}: ${value}`); 
    } 

    ngAfterContentInit(): void { 
    this.inputs.toArray().forEach((input, index) => { 
     input.inputChange$.subscribe(value => this.onChange(value, index + 1)); 
    }); 
    } 
} 

यहाँ आप अपने इनपुट तत्व पर एक ngControl जोड़ सकता है plunker sample

+0

धन्यवाद। सबसे पहले, मुझे लगता है कि मुझे आरएक्सजेएस का उपयोग करने की ज़रूरत है लेकिन यह बहुत जटिल है ... –

0

है।

<form> 
    <textbox> 
    <input ngControl="test"/> 
    </textbox> 
</form> 

इस तरह आप ContentChild के भीतर NgControl का उपयोग करने में सक्षम होंगे। यह वैल्यू चेंज संपत्ति तक पहुंच को टिग करता है जिसे आप अपडेट के अधिसूचित होने के लिए पंजीकृत कर सकते हैं।

@Component({ selector: 'textbox', ... }) 
export class TextboxComponent { 
    @ContentChild(NgControl) input: NgControl; 
    ngAfterContentInit(): void { 
    this.input.control.valueChanges.subscribe((): void => { 
     (...) 
    }); 
    } 
} 
+0

धन्यवाद। मुझे 'ngAfterContentInit' का उपयोग करने की वजह से उम्मीद नहीं की जा सकती है। 'NgAfterViewchecked' का उपयोग करते समय मुझे उत्सर्जित घटना मिली, लेकिन इसे कई बार निष्पादित किया गया ... –

4

ngAfterViewInit() में पर सुनी जा सकती है, (, ब्याज के तत्व (रों) लगता है तो लाजि़मी घटना श्रोता जोड़ने रों)।

@Component({ 
    selector: 'textbox', 
    template: `<h3>textbox value: {{inputValue}}</h3> 
     <div class="textbox-wrapper"> 
     <ng-content></ng-content> 
     </div>`, 
}) 
export class TextboxComp { 
    inputValue:string; 
    removeListenerFunc: Function; 
    constructor(private _elRef:ElementRef, private _renderer:Renderer) {} 
    ngAfterContentInit() { 
    let inputElement = this._elRef.nativeElement.querySelector('input'); 
    this.removeListenerFunc = this._renderer.listen(
     inputElement, 'input', 
     event => this.inputValue = event.target.value) 
    } 
    ngOnDestroy() { 
    this.removeListenerFunc(); 
    } 
} 

Plunker

इस उत्तर अनिवार्य रूप से, एक जरूरी दृष्टिकोण है गुंटर के कथात्मक दृष्टिकोण के विपरीत: नीचे कोड केवल एक ही इनपुट मान लिया गया है। यदि आपके पास एकाधिक इनपुट हैं तो यह दृष्टिकोण विस्तार करना आसान हो सकता है।


वहाँ उपयोगकर्ता के आपूर्ति टेम्पलेट (यानी, एनजी-सामग्री सामग्री) में डोम तत्वों को खोजने के लिए @ContentChild() (या @ContentChildren()) का उपयोग करने के लिए एक तरीका हो प्रतीत नहीं होता है ... @ContentChild(input) नहीं करता है की तरह कुछ ' टी अस्तित्व में प्रतीत होता है। इसलिए मैं querySelector() का उपयोग करता हूं।

इस ब्लॉग पोस्ट में, http://angularjs.blogspot.co.at/2016/04/5-rookie-mistakes-to-avoid-with-angular.html, काड़ा एक input चयनकर्ता के साथ एक निर्देशक (InputItem कहते हैं) को परिभाषित करने का सुझाव और फिर @ContentChildren(InputItem) inputs: QueryList<InputItem>; का उपयोग कर। फिर हमें querySelector() का उपयोग करने की आवश्यकता नहीं है। हालांकि, मुझे विशेष रूप से इस दृष्टिकोण को पसंद नहीं है क्योंकि टेक्स्टबॉक्स कॉम्पोनेंट के उपयोगकर्ता को directives सरणी में इनपुट इटैम भी शामिल करना है (मुझे लगता है कि कुछ घटक दस्तावेज समस्या को हल कर सकते हैं, लेकिन मैं अभी भी प्रशंसक नहीं हूं)। इस दृष्टिकोण के लिए यहां एक plunker है।

+0

ओह, धन्यवाद! मैं संदर्भ के लिए इसका इस्तेमाल करूंगा। –

0

आप अपने मॉड्यूल में कोणीय CDK पर्यवेक्षकों https://material.angular.io/cdk/observers/api

आयात इस मॉड्यूल का उपयोग

import { ObserversModule } from '@angular/cdk/observers'; 

तो ng-content's पेरेंट तत्व में उपयोग कर सकते हैं

<div class="projected-content-wrapper (cdkObserveContent)="contentChanged()"> 
<ng-content></ng-content> 
</div>