कोणीय 2 में एक और घटक फ़ंक्शन को कैसे कॉल किया जाए


154

मेरे पास निम्नानुसार दो घटक हैं और मैं दूसरे घटक से एक फ़ंक्शन को कॉल करना चाहता हूं। दोनों घटकों को निर्देश का उपयोग करके तीसरे मूल घटक में शामिल किया गया है।

घटक 1:

@component(
    selector:'com1'
)
export class com1{
    function1(){...}
}

घटक 2:

@component(
    selector:'com2'
)
export class com2{
    function2(){...
        // i want to call function 1 from com1 here
    }
}

मैं का उपयोग कर की कोशिश की है @inputऔर @outputलेकिन मुझे समझ नहीं आता कि वास्तव में यह कैसे उपयोग करने के लिए और कैसे है कि समारोह, कर सकते हैं किसी को भी मदद कॉल करने के लिए?


जवाबों:


130

यदि com1 और com2 भाई-बहन हैं तो आप उपयोग कर सकते हैं

@component({
  selector:'com1',
})
export class com1{
  function1(){...}
}

com2 एक का उपयोग करके एक घटना का उत्सर्जन करता है EventEmitter

@component({
  selector:'com2',
  template: `<button (click)="function2()">click</button>`
)
export class com2{
  @Output() myEvent = new EventEmitter();
  function2(){...
    this.myEvent.emit(null)
  }
}

यहां पैरेंट कंपोनेंट myEventईवेंट्स को सुनने के लिए एक इवेंट बाइंडिंग जोड़ता है और फिर com1.function1()इस तरह की घटना होने पर कॉल करता है। #com1एक टेम्प्लेट वैरिएबल है जो टेम्पलेट में कहीं से इस तत्व को संदर्भित करने की अनुमति देता है। हम इसका उपयोग function1()इवेंट हैंडलर बनाने के लिए करते myEventहैं com2:

@component({
  selector:'parent',
  template: `<com1 #com1></com1><com2 (myEvent)="com1.function1()"></com2>`
)
export class com2{
}

घटकों के बीच संवाद करने के अन्य विकल्पों के लिए भी घटक-इंटरैक्शन देखें


आपके प्रश्न में माता-पिता-बच्चे के बारे में कुछ भी नहीं है। आप क्या हासिल करने की कोशिश करते हैं?
गुंटर ज़ोचाउर

जब आपने कहना शुरू किया "यहाँ माता-पिता के घटक ने मायएवेंट को सुनने के लिए एक घटना को जोड़ा", मैं बहुत उलझन में हूँ। मुझे लगा कि हम भाई-बहन की घटक स्थिति को हल करने की कोशिश कर रहे हैं। कोणीय लिंक सभी माता-पिता का बच्चा है, इसलिए मैं उन का उपयोग नहीं कर सकता।
एंजेला पी

यह rhe भाई-बहनों के माता-पिता हैं (आप मेजबान भी कह सकते हैं)। <sibling1 (myEvent)="...">पैरेंट / होस्ट के लिए एक ईवेंट बाइंडिंग है, क्योंकि यह एकमात्र तरीका है जो कोणीय प्रदान करता है। हालांकि ईवेंट हैंडलर दूसरे सिबलिंग ( com1) पर एक विधि कहता है । जनक का उपयोग मध्यस्थ के रूप में किया जाता है।
गुंटर जोचबॉयर

कैसे इसे देखने से बाहर कॉल करने के लिए ?! बस अंदर somecomponent.ts?
मोहम्मद करमानी

लेकिन अगर सूची में कुछ उपयोगकर्ता के लिए दो अलग घटक (ऑन क्लिक इवेंट ((एक घटक))) और विस्तार पृष्ठ (अन्य घटक) पर घटना पर क्लिक करने वाली कॉपी - एक घटक विधि से मैं दूसरे घटक में उपयोग करना चाहता हूं, तो वह कैसे करें कृपया मुझे बताओ ??? @ गुंटरेज़ोचबॉयर
जिग्नेश वाघ

164

सबसे पहले, आपको घटकों के बीच संबंधों को समझने की आवश्यकता है। तब आप संचार का सही तरीका चुन सकते हैं। मैं उन सभी तरीकों की व्याख्या करने की कोशिश करूंगा जो मैं जानता हूं और घटकों के बीच संचार के लिए अपने अभ्यास में उपयोग करता हूं।

घटकों के बीच किस प्रकार के संबंध हो सकते हैं?

1. जनक> बाल

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

इनपुट के माध्यम से डेटा साझा करना

यह संभवतः डेटा साझा करने का सबसे आम तरीका है। यह @Input()टेम्पलेट के माध्यम से डेटा को पारित करने की अनुमति देने के लिए डेकोरेटर का उपयोग करके काम करता है ।

parent.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'parent-component',
  template: `
    <child-component [childProperty]="parentProperty"></child-component>
  `,
  styleUrls: ['./parent.component.css']
})
export class ParentComponent{
  parentProperty = "I come from parent"
  constructor() { }
}

child.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'child-component',
  template: `
      Hi {{ childProperty }}
  `,
  styleUrls: ['./child.component.css']
})
export class ChildComponent {

  @Input() childProperty: string;

  constructor() { }

}

यह एक बहुत ही सरल विधि है। यह प्रयोग करने में आसान है। हम ngOnChanges का उपयोग करके बाल घटक में डेटा में परिवर्तन भी पकड़ सकते हैं ।

लेकिन यह मत भूलो कि यदि हम किसी ऑब्जेक्ट को डेटा के रूप में उपयोग करते हैं और इस ऑब्जेक्ट के मापदंडों को बदलते हैं, तो इसका संदर्भ नहीं बदलेगा। इसलिए, यदि हम एक बच्चे के घटक में एक संशोधित वस्तु प्राप्त करना चाहते हैं, तो यह अपरिवर्तनीय होना चाहिए।

2. बच्चा> जनक

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

ViewChild के माध्यम से डेटा साझा करना

ViewChild एक घटक को दूसरे में इंजेक्ट करने की अनुमति देता है, जिससे माता-पिता अपनी विशेषताओं और कार्यों तक पहुंच प्राप्त कर सकते हैं। हालाँकि, एक चेतावनी, यह childतब तक उपलब्ध नहीं होगी जब तक कि दृश्य आरंभ नहीं हो जाता। इसका मतलब है कि हमें बच्चे से डेटा प्राप्त करने के लिए AfterViewInit जीवनचक्र हुक को लागू करने की आवश्यकता है।

parent.component.ts

import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from "../child/child.component";

@Component({
  selector: 'parent-component',
  template: `
    Message: {{ message }}
    <child-compnent></child-compnent>
  `,
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements AfterViewInit {

  @ViewChild(ChildComponent) child;

  constructor() { }

  message:string;

  ngAfterViewInit() {
    this.message = this.child.message
  }
}

child.component.ts

import { Component} from '@angular/core';

@Component({
  selector: 'child-component',
  template: `
  `,
  styleUrls: ['./child.component.css']
})
export class ChildComponent {

  message = 'Hello!';

  constructor() { }

}

आउटपुट () और EventEmitter के माध्यम से डेटा साझा करना

डेटा साझा करने का एक और तरीका है, बच्चे से डेटा का उत्सर्जन करना, जिसे माता-पिता द्वारा सूचीबद्ध किया जा सकता है। यह दृष्टिकोण आदर्श है जब आप डेटा परिवर्तनों को साझा करना चाहते हैं जो बटन क्लिक, फ़ॉर्म प्रविष्टियाँ और अन्य उपयोगकर्ता घटनाओं जैसी चीज़ों पर होते हैं।

parent.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'parent-component',
  template: `
    Message: {{message}}
    <child-component (messageEvent)="receiveMessage($event)"></child-component>
  `,
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {

  constructor() { }

  message:string;

  receiveMessage($event) {
    this.message = $event
  }
}

child.component.ts

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'child-component',
  template: `
      <button (click)="sendMessage()">Send Message</button>
  `,
  styleUrls: ['./child.component.css']
})
export class ChildComponent {

  message: string = "Hello!"

  @Output() messageEvent = new EventEmitter<string>();

  constructor() { }

  sendMessage() {
    this.messageEvent.emit(this.message)
  }
}

3. भाई बहन

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

बाल> अभिभावक> बाल

मैं नीचे भाई-बहनों के बीच संवाद करने के अन्य तरीके समझाने की कोशिश करता हूँ। लेकिन आप पहले से ही उपरोक्त तरीकों को समझने के तरीकों में से एक को समझ सकते हैं।

parent.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'parent-component',
  template: `
    Message: {{message}}
    <child-one-component (messageEvent)="receiveMessage($event)"></child1-component>
    <child-two-component [childMessage]="message"></child2-component>
  `,
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {

  constructor() { }

  message: string;

  receiveMessage($event) {
    this.message = $event
  }
}

बच्चों के one.component.ts

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'child-one-component',
  template: `
      <button (click)="sendMessage()">Send Message</button>
  `,
  styleUrls: ['./child-one.component.css']
})
export class ChildOneComponent {

  message: string = "Hello!"

  @Output() messageEvent = new EventEmitter<string>();

  constructor() { }

  sendMessage() {
    this.messageEvent.emit(this.message)
  }
}

बच्चों के two.component.ts

import { Component, Input } from '@angular/core';

@Component({
  selector: 'child-two-component',
  template: `
       {{ message }}
  `,
  styleUrls: ['./child-two.component.css']
})
export class ChildTwoComponent {

  @Input() childMessage: string;

  constructor() { }

}

4. असंबंधित घटक

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

नीचे बताए गए सभी तरीकों का उपयोग घटकों के बीच संबंध के लिए उपरोक्त सभी विकल्पों के लिए किया जा सकता है। लेकिन प्रत्येक के अपने फायदे और नुकसान हैं।

एक सेवा के साथ डेटा साझा करना

ऐसे घटकों के बीच डेटा पास करते समय जिनमें एक सीधा संबंध नहीं होता है, जैसे कि भाई-बहन, नाती-पोते, आदि, तो आपको एक साझा सेवा का उपयोग करना चाहिए। जब आपके पास डेटा होता है जो हमेशा सिंक में होना चाहिए, तो मुझे इस स्थिति में RxJS BehaviorSubject बहुत उपयोगी लगता है।

data.service.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable()
export class DataService {

  private messageSource = new BehaviorSubject('default message');
  currentMessage = this.messageSource.asObservable();

  constructor() { }

  changeMessage(message: string) {
    this.messageSource.next(message)
  }

}

first.component.ts

import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";

@Component({
  selector: 'first-componennt',
  template: `
    {{message}}
  `,
  styleUrls: ['./first.component.css']
})
export class FirstComponent implements OnInit {

  message:string;

  constructor(private data: DataService) {
      // The approach in Angular 6 is to declare in constructor
      this.data.currentMessage.subscribe(message => this.message = message);
  }

  ngOnInit() {
    this.data.currentMessage.subscribe(message => this.message = message)
  }

}

second.component.ts

import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";

@Component({
  selector: 'second-component',
  template: `
    {{message}}
    <button (click)="newMessage()">New Message</button>
  `,
  styleUrls: ['./second.component.css']
})
export class SecondComponent implements OnInit {

  message:string;

  constructor(private data: DataService) { }

  ngOnInit() {
    this.data.currentMessage.subscribe(message => this.message = message)
  }

  newMessage() {
    this.data.changeMessage("Hello from Second Component")
  }

}

एक रूट के साथ डेटा साझा करना

कभी-कभी आपको न केवल घटक के बीच सरल डेटा को पारित करने की आवश्यकता होती है, बल्कि पृष्ठ की कुछ स्थिति को बचाते हैं। उदाहरण के लिए, हम ऑनलाइन बाज़ार में कुछ फ़िल्टर सहेजना चाहते हैं और फिर इस लिंक को कॉपी करके किसी मित्र को भेज सकते हैं। और हम उम्मीद करते हैं कि यह हमारे जैसे ही राज्य में पेज खोलेगा। पहला, और शायद सबसे तेज़, ऐसा करने का तरीका क्वेरी मापदंडों का उपयोग करना होगा ।

क्वेरी पैरामीटर उन रेखाओं के साथ अधिक दिखते हैं /people?id=जहां idकुछ भी समान हो सकता है और आपके पास जितने चाहें उतने पैरामीटर हो सकते हैं। क्वेरी पैरामीटर एम्परसेंड वर्ण द्वारा अलग किया जाएगा।

क्वेरी पैरामीटर के साथ काम करते समय, आपको उन्हें अपने रूट फ़ाइल में परिभाषित करने की आवश्यकता नहीं है, और उन्हें पैरामीटर नाम दिया जा सकता है। उदाहरण के लिए, निम्नलिखित कोड लें:

page1.component.ts

import {Component} from "@angular/core";
import {Router, NavigationExtras} from "@angular/router";

@Component({
    selector: "page1",
  template: `
    <button (click)="onTap()">Navigate to page2</button>
  `,
})
export class Page1Component {

    public constructor(private router: Router) { }

    public onTap() {
        let navigationExtras: NavigationExtras = {
            queryParams: {
                "firstname": "Nic",
                "lastname": "Raboy"
            }
        };
        this.router.navigate(["page2"], navigationExtras);
    }

}

प्राप्त करने वाले पृष्ठ में, आपको निम्न तरह से ये क्वेरी पैरामीटर प्राप्त होंगे:

page2.component.ts

import {Component} from "@angular/core";
import {ActivatedRoute} from "@angular/router";

@Component({
    selector: "page2",
    template: `
         <span>{{firstname}}</span>
         <span>{{lastname}}</span>
      `,
})
export class Page2Component {

    firstname: string;
    lastname: string;

    public constructor(private route: ActivatedRoute) {
        this.route.queryParams.subscribe(params => {
            this.firstname = params["firstname"];
            this.lastname = params["lastname"];
        });
    }

}

NgRx

अंतिम तरीका, जो अधिक जटिल है लेकिन अधिक शक्तिशाली है, NgRx का उपयोग करना है । यह लाइब्रेरी डेटा शेयरिंग के लिए नहीं है; यह एक शक्तिशाली राज्य प्रबंधन पुस्तकालय है। मैं एक छोटे उदाहरण में नहीं बता सकता कि इसका उपयोग कैसे करना है, लेकिन आप आधिकारिक साइट पर जा सकते हैं और इसके बारे में प्रलेखन पढ़ सकते हैं।

मेरे लिए, NgRx Store कई मुद्दों को हल करता है। उदाहरण के लिए, जब आपको वेधशालाओं से निपटना होता है और जब अलग-अलग घटकों के बीच कुछ अवलोकन योग्य डेटा के लिए जिम्मेदारी साझा की जाती है, तो स्टोर क्रिया और reducer सुनिश्चित करता है कि डेटा संशोधनों को हमेशा "सही तरीके" से किया जाएगा।

यह HTTP अनुरोध कैशिंग के लिए एक विश्वसनीय समाधान भी प्रदान करता है। आप अनुरोधों और उनकी प्रतिक्रियाओं को संग्रहीत करने में सक्षम होंगे ताकि आप यह सत्यापित कर सकें कि आप जो अनुरोध कर रहे हैं वह अभी तक संग्रहीत प्रतिक्रिया नहीं है।

आप NgRx के बारे में पढ़ सकते हैं और समझ सकते हैं कि आपको अपने ऐप में इसकी आवश्यकता है या नहीं:

अंत में, मैं कहना चाहता हूं कि डेटा साझा करने के कुछ तरीकों को चुनने से पहले आपको यह समझने की आवश्यकता है कि भविष्य में इस डेटा का उपयोग कैसे किया जाएगा। मेरा मतलब है कि शायद अब आप @Inputएक उपयोगकर्ता नाम और उपनाम साझा करने के लिए सिर्फ एक डेकोरेटर का उपयोग कर सकते हैं । फिर आप एक नया घटक या नया मॉड्यूल जोड़ेंगे (उदाहरण के लिए, एक व्यवस्थापक पैनल) जिसे उपयोगकर्ता के बारे में अधिक जानकारी की आवश्यकता है। इसका मतलब है कि उपयोगकर्ता डेटा या किसी अन्य तरीके से डेटा साझा करने के लिए किसी सेवा का उपयोग करने का एक बेहतर तरीका हो सकता है। डेटा साझाकरण को लागू करने से पहले आपको इसके बारे में अधिक सोचने की आवश्यकता है।


3
उदाहरणों के साथ सबसे अच्छा विवरण
afeef

1
इस विषय का सबसे अच्छा जवाब जो मैंने कभी देखा है, बधाई हो, ..
लोनली

एक्सेलेंट स्पष्टीकरण
Moisés Aguilar

3 में। भाई-बहन ts-child.com दो html में प्रदर्शित नाम। चाइल्ड मैसेजेज होना चाहिए। (केस के लिए html फाइल का इस्तेमाल करें)
Nam Nguyễn

84

आप घटक दो से घटक की विधि तक पहुँच सकते हैं।

componentOne

  ngOnInit() {}

  public testCall(){
    alert("I am here..");    
  }

componentTwo

import { oneComponent } from '../one.component';


@Component({
  providers:[oneComponent ],
  selector: 'app-two',
  templateUrl: ...
}


constructor(private comp: oneComponent ) { }

public callMe(): void {
    this.comp.testCall();
  }

ComponentsTwo HTML फ़ाइल

<button (click)="callMe()">click</button>

2
यह मेरे लिए तब तक था जब तक कि मुझे testCall को कंपोनेंटव्यू से कंपोनेंटऑन में एक वैरिएबल एक्सेस करने के लिए जरूरी था। .... वह केस जिसके लिए वैरिएबल वैल्यू को कंपोनेंट द्वारा सेट किया गया है, लेकिन कंपोनेंटो को डिफॉल्ट मिलेगा और करंट नहीं।
२०:३० पर rey_coder

2
अगर मुझे testCall घटक से कॉल किया जाता है, तो मुझे testCall विधि के अंदर कंपोनेंट चर मान नहीं मिल रहे हैं। कोई उपाय?
राजा

कृपया इस विधि को Ionic 4 के लिए कोणीय 7
मोहम्मद अय्यूब खान के साथ

इस तरह से यह @ रजा को एक ही समस्या नहीं देता है
केविन डायस

1
THQQQQQQQQQQQQ SO MUCH MAN
आशु

33

घटक 1 (बच्चा):

@Component(
  selector:'com1'
)
export class Component1{
  function1(){...}
}

घटक 2 (मूल):

@Component(
  selector:'com2',
  template: `<com1 #component1></com1>`
)
export class Component2{
  @ViewChild("component1") component1: Component1;

  function2(){
    this.component1.function1();
  }
}

अच्छा जवाब है, यह भी देखना यहां
सिफर

सब ठीक है कि मैं HTML पर function2 कैसे कहूं? मुझे हमेशा यह पता चला है।
com नापसंद

<com1 # Components1 (क्लिक करें) = "function2 ()"> </ com1>
Ihor Khomiak

1
यह मेरे लिए काम कर रहा है, एक बार मुझे एहसास हुआ कि आपको @ कोणीय / कोर से ViewChild आयात करना होगा और जहां भी यह है वहां से Comp1 भी।
डलास कैले

1
घटक वर्ग का विस्तार करने के बजाय, मैं uesd @ViewChildजो मेरे लिए काम किया। इस उदाहरण के लिए धन्यवाद।
यश

27

यह आपके घटकों (माता-पिता / बच्चे) के बीच संबंध पर निर्भर करता है, लेकिन संचार घटकों को बनाने का सबसे अच्छा / सामान्य तरीका एक साझा सेवा का उपयोग करना है।

अधिक जानकारी के लिए यह दस्तावेज़ देखें:

कहा जा रहा है, आप com1 में com1 का एक उदाहरण प्रदान करने के लिए निम्नलिखित का उपयोग कर सकते हैं:

<div>
  <com1 #com1>...</com1>
  <com2 [com1ref]="com1">...</com2>
</div>

Com2 में, आप निम्नलिखित का उपयोग कर सकते हैं:

@Component({
  selector:'com2'
})
export class com2{
  @Input()
  com1ref:com1;

  function2(){
    // i want to call function 1 from com1 here
    this.com1ref.function1();
  }
}

मैं त्रुटि प्राप्त कर रहा हूँ 'com1Ref' को नहीं बांध सकता क्योंकि यह एक ज्ञात मूल संपत्ति नहीं है
noobProgrammer

और इसके इस com1.function1 () नहीं ले रहा है; इसके बजाय इस .1ref.function1 ();
noobProgrammer

टाइपो को इंगित करने के लिए धन्यवाद! क्या आप @Inputमैदान पर हैं?
थिएरी टेम्पलर

ठीक है इसकी कार्यप्रणाली, क्या आप बता सकते हैं कि माता-पिता - बाल संबंध के लिए समान कैसे प्राप्त करें ??
noobProgrammer

1
मैंने माता-पिता के बच्चे के लिए भी ऐसा ही प्रयास किया है, लेकिन यह कहा जाता है कि कार्य 1 () अनिर्दिष्ट
noobProgrammer

1
  • कहते हैं कि पहला घटक DbstatsMainComponent है
  • दूसरा घटक DbstatsGraphComponent।
  • 1 घटक 2 की विधि को बुला रहा है

<button (click)="dbgraph.displayTableGraph()">Graph</button> <dbstats-graph #dbgraph></dbstats-graph>

#dbgraphबच्चे के घटक पर स्थानीय चर पर ध्यान दें , जिसका उपयोग माता-पिता अपने तरीकों ( dbgraph.displayTableGraph()) तक पहुंचने के लिए कर सकते हैं ।


0

Dataservice का उपयोग करके हम फ़ंक्शन को किसी अन्य घटक से कॉल कर सकते हैं

घटक 1: वह घटक जिसे हम फ़ंक्शन कह रहे हैं

constructor( public bookmarkRoot: dataService ) { } 

onClick(){
     this.bookmarkRoot.callToggle.next( true );
}

dataservice.ts

import { Injectable } from '@angular/core';
@Injectable()
export class dataService {
     callToggle = new Subject();
}

घटक 2: घटक जिसमें फ़ंक्शन होता है

constructor( public bookmarkRoot: dataService ) { 
  this.bookmarkRoot.callToggle.subscribe(( data ) => {
            this.closeDrawer();
        } )
} 

 closeDrawer() {
        console.log("this is called")
    }

इससे बचने के लिए कई बार कॉल कर सकते हैं कि इस कोड का इस्तेमाल कंस्ट्रक्टर के अंदर करेंif ( this.bookmarkRoot.callToggle.observers.length === 0 ) { this.bookmarkRoot.callToggle.subscribe(( data ) => { this.closeDrawer(); } ) }
Shafeeq Mohammed
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.