เหตุการณ์ระดับโลกในเชิงมุม


224

ไม่เทียบเท่า$scope.emit()หรือ$scope.broadcast()ในเชิงมุม?

ฉันรู้ถึงEventEmitterฟังก์ชั่นการใช้งาน แต่เท่าที่ฉันเข้าใจว่าจะปล่อยเหตุการณ์ไปยังองค์ประกอบ HTML หลัก

จะทำอย่างไรถ้าฉันต้องการสื่อสารระหว่าง fx พี่น้องหรือระหว่างองค์ประกอบในรากของ DOM และองค์ประกอบซ้อนกันหลายระดับลึก?


2
ฉันมีคำถามที่คล้ายกันที่เกี่ยวข้องกับการสร้างองค์ประกอบโต้ตอบที่สามารถเข้าถึงได้จากจุดใด ๆ ใน dom: stackoverflow.com/questions/34572539// โดยทั่วไปวิธีการแก้ปัญหาหนึ่งคือการวางอีซีแอลเหตุการณ์ในบริการ
brando

1
นี่คือการดำเนินการของฉันของบริการดังกล่าวโดยใช้ RXJS ที่อนุญาตให้รับค่า nth ล่าสุดเมื่อสมัครสมาชิก stackoverflow.com/questions/46027693/…
Codewarrior

คำตอบ:


385

ไม่มีอะไรเทียบเท่า$scope.emit()หรือ$scope.broadcast()จาก AngularJS EventEmitter ด้านในขององค์ประกอบใกล้เข้ามา แต่อย่างที่คุณพูดถึงมันจะส่งเหตุการณ์ไปยังองค์ประกอบหลักเท่านั้น

ในเชิงมุมมีทางเลือกอื่นที่ฉันจะพยายามอธิบายด้านล่าง

@Input () bindings อนุญาตให้โมเดลแอปพลิเคชันเชื่อมต่อในกราฟวัตถุที่กำหนดทิศทาง (root to leaves) พฤติกรรมเริ่มต้นของกลยุทธ์เครื่องมือตรวจจับการเปลี่ยนแปลงของส่วนประกอบคือการเผยแพร่การเปลี่ยนแปลงทั้งหมดในรูปแบบของแอปพลิเคชันสำหรับการผูกทั้งหมดจากองค์ประกอบที่เชื่อมต่อใด ๆ

ด้านข้าง: มีสองรุ่น: ดูรุ่นและรุ่นของแอปพลิเคชัน โมเดลของแอปพลิเคชันเชื่อมต่อผ่านการผูก @Input () รูปแบบการดูเป็นเพียงคุณสมบัติของส่วนประกอบ (ไม่ได้ตกแต่งด้วย @Input ()) ซึ่งถูกผูกไว้ในแม่แบบของส่วนประกอบ

เพื่อตอบคำถามของคุณ:

ถ้าฉันต้องการสื่อสารระหว่างส่วนประกอบของพี่น้อง

  1. Shared Application Model : พี่น้องสามารถสื่อสารผ่านโมเดลแอปพลิเคชันที่ใช้ร่วมกันได้ (เช่นเดียวกับเชิงมุม 1) ตัวอย่างเช่นเมื่อพี่น้องหนึ่งทำการเปลี่ยนแปลงกับโมเดลพี่น้องอื่น ๆ ที่มีการเชื่อมโยงกับโมเดลเดียวกันจะถูกอัพเดตโดยอัตโนมัติ

  2. เหตุการณ์ส่วนประกอบ : องค์ประกอบลูกสามารถส่งเหตุการณ์ไปยังองค์ประกอบหลักโดยใช้ @Output () การเชื่อมโยง คอมโพเนนต์พาเรนต์สามารถจัดการกับเหตุการณ์และจัดการโมเดลแอ็พพลิเคชันหรือเป็นโมเดลมุมมองของตัวเอง การเปลี่ยนแปลงรูปแบบของแอปพลิเคชันจะแพร่กระจายโดยอัตโนมัติไปยังส่วนประกอบทั้งหมดที่ผูกโดยตรงหรือโดยอ้อมกับรุ่นเดียวกัน

  3. กิจกรรมบริการ : ส่วนประกอบสามารถสมัครสมาชิกกับกิจกรรมบริการ ตัวอย่างเช่นสององค์ประกอบพี่น้องสามารถสมัครใช้งานบริการเดียวกันและตอบสนองโดยการปรับเปลี่ยนรูปแบบที่เกี่ยวข้อง เพิ่มเติมเกี่ยวกับเรื่องนี้ด้านล่าง

ฉันจะสื่อสารระหว่างองค์ประกอบรูทและส่วนประกอบที่ซ้อนกันหลายระดับได้อย่างไร

  1. Shared Application Model : โมเดลแอปพลิเคชันสามารถส่งผ่านจากรูทคอมโพเนนต์ไปยังคอมโพเนนต์ย่อยที่อยู่ลึกลงไปผ่านการผูก @Input () การเปลี่ยนแปลงโมเดลจากคอมโพเนนต์ใด ๆ จะเผยแพร่ไปยังคอมโพเนนต์ทั้งหมดที่ใช้โมเดลเดียวกันโดยอัตโนมัติ
  2. กิจกรรมบริการ : คุณสามารถย้าย EventEmitter ไปยังบริการที่ใช้ร่วมกันซึ่งอนุญาตให้ส่วนประกอบใด ๆ เพื่อฉีดบริการและสมัครรับกิจกรรม ด้วยวิธีนี้คอมโพเนนต์รูทสามารถเรียกใช้เมธอดเซอร์วิส (โดยทั่วไปจะกลายพันธุ์โมเดล) ซึ่งจะส่งเหตุการณ์ออกมา มีเลเยอร์หลายชั้นซึ่งเป็นองค์ประกอบของลูกหลานที่ฉีดบริการและสมัครเป็นสมาชิกของเหตุการณ์เดียวกันก็สามารถจัดการได้ ตัวจัดการเหตุการณ์ใด ๆ ที่เปลี่ยนโมเดลแอปพลิเคชันที่ใช้ร่วมกันจะเผยแพร่ไปยังคอมโพเนนต์ทั้งหมดที่ขึ้นอยู่กับมันโดยอัตโนมัติ นี่น่าจะใกล้เคียงที่สุดกับ$scope.broadcast()จาก Angular 1 ส่วนถัดไปอธิบายแนวคิดนี้ในรายละเอียดเพิ่มเติม

ตัวอย่างของบริการที่สังเกตได้ซึ่งใช้เหตุการณ์บริการเพื่อเผยแพร่การเปลี่ยนแปลง

นี่คือตัวอย่างของบริการที่สังเกตได้ซึ่งใช้กิจกรรมบริการเพื่อเผยแพร่การเปลี่ยนแปลง เมื่อมีการเพิ่ม TodoItem บริการจะปล่อยเหตุการณ์ที่แจ้งสมาชิกสมาชิก

export class TodoItem {
    constructor(public name: string, public done: boolean) {
    }
}
export class TodoService {
    public itemAdded$: EventEmitter<TodoItem>;
    private todoList: TodoItem[] = [];

    constructor() {
        this.itemAdded$ = new EventEmitter();
    }

    public list(): TodoItem[] {
        return this.todoList;
    }

    public add(item: TodoItem): void {
        this.todoList.push(item);
        this.itemAdded$.emit(item);
    }
}

นี่คือวิธีที่องค์ประกอบรูทจะสมัครสมาชิกของเหตุการณ์:

export class RootComponent {
    private addedItem: TodoItem;
    constructor(todoService: TodoService) {
        todoService.itemAdded$.subscribe(item => this.onItemAdded(item));
    }

    private onItemAdded(item: TodoItem): void {
        // do something with added item
        this.addedItem = item;
    }
}

องค์ประกอบย่อยที่ซ้อนกันหลายระดับลึกจะสมัครเป็นสมาชิกของเหตุการณ์ในลักษณะเดียวกัน:

export class GrandChildComponent {
    private addedItem: TodoItem;
    constructor(todoService: TodoService) {
        todoService.itemAdded$.subscribe(item => this.onItemAdded(item));
    }

    private onItemAdded(item: TodoItem): void {
        // do something with added item
        this.addedItem = item;
    }
}

นี่คือส่วนประกอบที่เรียกใช้บริการเพื่อทริกเกอร์เหตุการณ์ (สามารถอยู่ที่ใดก็ได้ในโครงสร้างส่วนประกอบ):

@Component({
    selector: 'todo-list',
    template: `
         <ul>
            <li *ngFor="#item of model"> {{ item.name }}
            </li>
         </ul>
        <br />
        Add Item <input type="text" #txt /> <button (click)="add(txt.value); txt.value='';">Add</button>
    `
})
export class TriggeringComponent{
    private model: TodoItem[];

    constructor(private todoService: TodoService) {
        this.model = todoService.list();
    }

    add(value: string) {
        this.todoService.add(new TodoItem(value, false));
    }
}

การอ้างอิง: การตรวจจับการเปลี่ยนแปลงในเชิงมุม


27
ผมเคยเห็นต่อท้าย $ ในการโพสต์ไม่กี่ตอนการสังเกตหรือ EventEmitter - itemAdded$เช่น นั่นคือการประชุม RxJS หรืออะไรบางอย่าง? สิ่งนี้มาจากไหน
Mark Rajcok

1
คำตอบที่ดี คุณกล่าวว่า "การเปลี่ยนแปลงในรูปแบบแอปจะแพร่กระจายไปยังองค์ประกอบทั้งหมดโดยอัตโนมัติซึ่งผูกกับรูปแบบเดียวกันทั้งทางตรงและทางอ้อม" ฉันมีลางสังหรณ์ว่ามันค่อนข้างใช้งานไม่ได้ (แต่ฉันไม่แน่ใจ) Savkin อื่น ๆโพสต์บล็อกให้เห็นตัวอย่างขององค์ประกอบการเปลี่ยนแปลงที่streetคุณสมบัติของรูปแบบแอป แต่เนื่องจากเชิงมุม 2 การดำเนินการเปลี่ยนการตรวจสอบเอกลักษณ์ / อ้างอิงไม่มีการเปลี่ยนแปลงที่จะแพร่กระจาย ( onChangesไม่ได้เรียกว่า) เพราะการอ้างอิงรูปแบบแอปไม่ได้เปลี่ยนแปลง ( ต่อ ... )
Mark Rajcok

10
คุณอาจต้องการอัปเดตคำตอบของคุณเพื่อใช้ Observable แทน EventEmitter ในบริการ ดูstackoverflow.com/a/35568924/215945และstackoverflow.com/questions/36076700
Mark Rajcok

2
ใช่ส่วนต่อท้าย $ เป็นแบบแผน RxJS ที่ได้รับความนิยมโดย Cycle.js cycle.js.org/…
jody tate

4
คุณไม่ควรสมัครรับจดหมายข่าวด้วยตนเอง มันอาจจะไม่ใช่สิ่งที่สังเกตได้ในการเปิดตัวครั้งสุดท้าย! ดูสิ่งนี้: bennadel.com/blog/…
NetProvoke

49

รหัสต่อไปนี้เป็นตัวอย่างของการแทนที่สำหรับ$ scope.emit ()หรือ$ scope.broadcast ()ใน Angular 2 โดยใช้บริการที่ใช้ร่วมกันเพื่อจัดการเหตุการณ์

import {Injectable} from 'angular2/core';
import * as Rx from 'rxjs/Rx';

@Injectable()
export class EventsService {
    constructor() {
        this.listeners = {};
        this.eventsSubject = new Rx.Subject();

        this.events = Rx.Observable.from(this.eventsSubject);

        this.events.subscribe(
            ({name, args}) => {
                if (this.listeners[name]) {
                    for (let listener of this.listeners[name]) {
                        listener(...args);
                    }
                }
            });
    }

    on(name, listener) {
        if (!this.listeners[name]) {
            this.listeners[name] = [];
        }

        this.listeners[name].push(listener);
    }

    off(name, listener) {
        this.listeners[name] = this.listeners[name].filter(x => x != listener);
    }

    broadcast(name, ...args) {
        this.eventsSubject.next({
            name,
            args
        });
    }
}

ตัวอย่างการใช้งาน:

ออกอากาศ:

function handleHttpError(error) {
    this.eventsService.broadcast('http-error', error);
    return ( Rx.Observable.throw(error) );
}

ฟัง:

import {Inject, Injectable} from "angular2/core";
import {EventsService}      from './events.service';

@Injectable()
export class HttpErrorHandler {
    constructor(eventsService) {
        this.eventsService = eventsService;
    }

    static get parameters() {
        return [new Inject(EventsService)];
    }

    init() {
        this.eventsService.on('http-error', function(error) {
            console.group("HttpErrorHandler");
            console.log(error.status, "status code detected.");
            console.dir(error);
            console.groupEnd();
        });
    }
}

มันสามารถรองรับการขัดแย้งกัน:

this.eventsService.broadcast('something', "Am I a?", "Should be b", "C?");

this.eventsService.on('something', function (a, b, c) {
   console.log(a, b, c);
});

สิ่งนี้ทำอะไร พารามิเตอร์ get แบบสแตติก () {return [Inject ใหม่ (EventsService)]; }
Beanwah

ในตัวอย่างนี้ฉันใช้ Ionic 2 Framework วิธีการพารามิเตอร์แบบคงที่จะเรียกว่าเมื่อมีการเรียกใช้วิธีการสร้างและใช้ในการจัดหาการอ้างอิงไปยังตัวสร้าง คำอธิบายที่นี่stackoverflow.com/questions/35919593/…
jim.taylor.1974

1
ทำได้ดีมาก เรียบง่ายและมีระบบการแจ้งเตือนที่ปรับเปลี่ยนได้ง่ายสำหรับแอปทั้งหมดไม่ใช่เพียงครั้งเดียว
Mike M

ฉันเพิ่งสร้างบริการที่คล้ายกันด้วยการสนับสนุนสัญลักษณ์ หวังว่ามันจะช่วย github.com/govorov/ng-radio
Stanislav E. Govorov

2
เจ๋งใช้มัน แต่เพิ่มฟังก์ชั่นปิดถ้าสนใจอีกต่อไป: off(name, listener) { this.listeners[name] = this.listeners[name].filter(x => x != listener); }
LVDM

16

ฉันใช้บริการข้อความที่ล้อม rxjs Subject(TypeScript)

ตัวอย่าง Plunker: บริการข้อความ

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/filter'
import 'rxjs/add/operator/map'

interface Message {
  type: string;
  payload: any;
}

type MessageCallback = (payload: any) => void;

@Injectable()
export class MessageService {
  private handler = new Subject<Message>();

  broadcast(type: string, payload: any) {
    this.handler.next({ type, payload });
  }

  subscribe(type: string, callback: MessageCallback): Subscription {
    return this.handler
      .filter(message => message.type === type)
      .map(message => message.payload)
      .subscribe(callback);
  }
}

ส่วนประกอบสามารถสมัครและออกอากาศเหตุการณ์ (ผู้ส่ง):

import { Component, OnDestroy } from '@angular/core'
import { MessageService } from './message.service'
import { Subscription } from 'rxjs/Subscription'

@Component({
  selector: 'sender',
  template: ...
})
export class SenderComponent implements OnDestroy {
  private subscription: Subscription;
  private messages = [];
  private messageNum = 0;
  private name = 'sender'

  constructor(private messageService: MessageService) {
    this.subscription = messageService.subscribe(this.name, (payload) => {
      this.messages.push(payload);
    });
  }

  send() {
    let payload = {
      text: `Message ${++this.messageNum}`,
      respondEvent: this.name
    }
    this.messageService.broadcast('receiver', payload);
  }

  clear() {
    this.messages = [];
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

(รับ)

import { Component, OnDestroy } from '@angular/core'
import { MessageService } from './message.service'
import { Subscription } from 'rxjs/Subscription'

@Component({
  selector: 'receiver',
  template: ...
})
export class ReceiverComponent implements OnDestroy {
  private subscription: Subscription;
  private messages = [];

  constructor(private messageService: MessageService) {
    this.subscription = messageService.subscribe('receiver', (payload) => {
      this.messages.push(payload);
    });
  }

  send(message: {text: string, respondEvent: string}) {
    this.messageService.broadcast(message.respondEvent, message.text);
  }

  clear() {
    this.messages = [];
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

subscribeวิธีการในการMessageServiceส่งกลับ rxjs Subscriptionวัตถุซึ่งสามารถยกเลิกการสมัครเพื่อต้องการ:

import { Subscription } from 'rxjs/Subscription';
...
export class SomeListener {
  subscription: Subscription;

  constructor(private messageService: MessageService) {
    this.subscription = messageService.subscribe('someMessage', (payload) => {
      console.log(payload);
      this.subscription.unsubscribe();
    });
  }
}

ดูคำตอบนี้ด้วย: https://stackoverflow.com/a/36782616/1861779

ตัวอย่าง Plunker: บริการข้อความ


2
มีค่ามาก ขอบคุณสำหรับคำตอบ. ฉันเพิ่งพบว่าคุณไม่สามารถสื่อสารกับสององค์ประกอบในสองโมดูลที่แตกต่างกันโดยใช้วิธีนี้ เพื่อให้บรรลุเป้าหมายฉันต้องลงทะเบียน MessageService ในระดับ app.module โดยการเพิ่มผู้ให้บริการที่นั่น วิธีนี้เป็นวิธีที่เจ๋งจริงๆ
Rukshan Dangalla

ทั้งหมดนี้ล้าสมัยไปแล้ว โดยเฉพาะอย่างยิ่งผู้รวบรวมที่ไม่โหลดทรัพยากรใด ๆ สำเร็จ พวกเขาทั้งหมด 500 รหัสข้อผิดพลาด
tatsu

ฉันได้รับProperty 'filter' does not exist on type 'Subject<EventMessage>'.
ดึง

@Drew this.handler.pipe(filter(...))ในรุ่นใหม่ของการใช้งาน ดูผู้ประกอบการโรงงานให้เช่า
t.888

1
@ t.888 ขอบคุณฉันคิดออก ฟังก์ชั่นการสมัครรับข้อมูลที่อัปเดตดูเหมือนreturn this.handler.pipe( filter(message => message.type === type), map(message => message.payload) ).subscribe(callback);
Drew

12

อย่าใช้ EventEmitter สำหรับการสื่อสารบริการของคุณ

คุณควรใช้หนึ่งในประเภทที่สังเกตได้ ฉันชอบ BehaviorSubject โดยส่วนตัว

ตัวอย่างง่ายๆ:

คุณสามารถผ่านสถานะเริ่มต้นที่นี่ฉันผ่าน null

ให้หัวเรื่อง = ใหม่ BehaviorSubject (null);

เมื่อคุณต้องการอัพเดทเรื่อง

subject.next (myObject)

สังเกตจากบริการหรือส่วนประกอบใด ๆ และดำเนินการเมื่อได้รับการอัพเดตใหม่

subject.subscribe (this.YOURMETHOD);

นี่คือข้อมูลเพิ่มเติม .


1
คุณช่วยอธิบายเหตุผลของการตัดสินใจออกแบบนี้ได้ไหม?
mtraut

@mtraut ลิงก์นั้นยังมีคำอธิบายที่ครอบคลุม
Danial Kalbasi

สำหรับคำอธิบายโดยละเอียดเพิ่มเติมเกี่ยวกับวิธีใช้ BehaviourSubject โปรดอ่านบทความนี้blog.cloudboost.io/…
rafalkasa

Eaxctly สิ่งที่ฉันต้องการ Nice and simple :)
ต่ำ

8

คุณสามารถใช้EventEmitter หรือ observables เพื่อสร้างบริการ eventbus ที่คุณลงทะเบียนกับ DI ทุกองค์ประกอบที่ต้องการมีส่วนร่วมเพียงแค่ร้องขอบริการเป็นพารามิเตอร์คอนสตรัคเตอร์และส่งเสียงและ / หรือสมัครสมาชิกกับเหตุการณ์

ดูสิ่งนี้ด้วย


2

วิธีที่ฉันชอบทำคือการใช้หัวเรื่องพฤติกรรมหรือตัวปล่อยเหตุการณ์ (เกือบเหมือนกัน) ในบริการของฉันเพื่อควบคุมส่วนประกอบย่อยทั้งหมดของฉัน

ใช้ angi cli เรียกใช้ ng gs เพื่อสร้างบริการใหม่จากนั้นใช้ BehaviorSubject หรือ EventEmitter

export Class myService {
#all the stuff that must exist

myString: string[] = [];
contactChange : BehaviorSubject<string[]> = new BehaviorSubject(this.myString);

   getContacts(newContacts) {
     // get your data from a webservices & when you done simply next the value 
    this.contactChange.next(newContacts);
   }
}

เมื่อคุณทำเช่นนั้นทุกองค์ประกอบที่ใช้บริการของคุณในฐานะผู้ให้บริการจะรับรู้ถึงการเปลี่ยนแปลง เพียงสมัครรับข้อมูลผลลัพธ์เช่นเดียวกับที่คุณทำกับ eventEmitter;)

export Class myComp {
#all the stuff that exists like @Component + constructor using (private myService: myService)

this.myService.contactChange.subscribe((contacts) => {
     this.contactList += contacts; //run everytime next is called
  }
}

1

ฉันได้สร้างตัวอย่างผับย่อยที่นี่:

http://www.syntaxsuccess.com/viewarticle/pub-sub-in-angular-2.0

แนวคิดคือการใช้ RxJs Subjects เพื่อวาง Observer และ Observables เป็นโซลูชันทั่วไปสำหรับการเปล่งและการสมัครสมาชิกกับเหตุการณ์ที่กำหนดเอง ในตัวอย่างของฉันฉันใช้วัตถุลูกค้าเพื่อการสาธิต

this.pubSubService.Stream.emit(customer);

this.pubSubService.Stream.subscribe(customer => this.processCustomer(customer));

นี่คือการสาธิตสดเช่นกัน: http://www.syntaxsuccess.com/angular-2-samples/#/demo/pub-sub


1

นี่คือรุ่นของฉัน:

export interface IEventListenr extends OnDestroy{
    ngOnDestroy(): void
}

@Injectable()
export class EventManagerService {


    private listeners = {};
    private subject = new EventEmitter();
    private eventObserver = this.subject.asObservable();


    constructor() {

        this.eventObserver.subscribe(({name,args})=>{



             if(this.listeners[name])
             {
                 for(let listener of this.listeners[name])
                 {
                     listener.callback(args);
                 }
             }
        })

    }

    public registerEvent(eventName:string,eventListener:IEventListenr,callback:any)
    {

        if(!this.listeners[eventName])
             this.listeners[eventName] = [];

         let eventExist = false;
         for(let listener of this.listeners[eventName])
         {

             if(listener.eventListener.constructor.name==eventListener.constructor.name)
             {
                 eventExist = true;
                 break;
             }
         }

        if(!eventExist)
        {
             this.listeners[eventName].push({eventListener,callback});
        }
    }

    public unregisterEvent(eventName:string,eventListener:IEventListenr)
    {

        if(this.listeners[eventName])
        {
            for(let i = 0; i<this.listeners[eventName].length;i++)
            {

                if(this.listeners[eventName][i].eventListener.constructor.name==eventListener.constructor.name)
                {
                    this.listeners[eventName].splice(i, 1);
                    break;
                }
            }
        }


    }


    emit(name:string,...args:any[])
    {
        this.subject.next({name,args});
    }
}

ใช้:

export class <YOURCOMPONENT> implements IEventListener{

  constructor(private eventManager: EventManagerService) {


    this.eventManager.registerEvent('EVENT_NAME',this,(args:any)=>{
       ....
    })


  }

  ngOnDestroy(): void {
    this.eventManager.unregisterEvent('closeModal',this)
  }

}

ปล่อย:

 this.eventManager.emit("EVENT_NAME");

0

เราใช้ ngModelChange คำสั่งที่สังเกตได้ซึ่งส่งการเปลี่ยนแปลงรูปแบบทั้งหมดผ่านตัวปล่อยเหตุการณ์ที่คุณสร้างอินสแตนซ์ในองค์ประกอบของคุณเอง คุณเพียงแค่ต้องผูกตัวส่งเหตุการณ์ของคุณกับคำสั่ง

โปรดดู: https://github.com/atomicbits/angular2-modelchangeobservable

ใน html ให้ผูกตัวปล่อยเหตุการณ์ของคุณ (countryChanged ในตัวอย่างนี้):

<input [(ngModel)]="country.name"
       [modelChangeObservable]="countryChanged" 
       placeholder="Country"
       name="country" id="country"></input>

ในคอมโพเนนต์ typescript ของคุณให้ดำเนินการ async บางอย่างบน EventEmitter:

import ...
import {ModelChangeObservable} from './model-change-observable.directive'


@Component({
    selector: 'my-component',
    directives: [ModelChangeObservable],
    providers: [],
    templateUrl: 'my-component.html'
})

export class MyComponent {

    @Input()
    country: Country

    selectedCountries:Country[]
    countries:Country[] = <Country[]>[]
    countryChanged:EventEmitter<string> = new EventEmitter<string>()


    constructor() {

        this.countryChanged
            .filter((text:string) => text.length > 2)
            .debounceTime(300)
            .subscribe((countryName:string) => {
                let query = new RegExp(countryName, 'ig')
                this.selectedCountries = this.countries.filter((country:Country) => {
                    return query.test(country.name)
                })
            })
    }
}

0

กิจกรรมบริการ: ส่วนประกอบสามารถสมัครสมาชิกกับกิจกรรมบริการ ตัวอย่างเช่นสององค์ประกอบพี่น้องสามารถสมัครเป็นสมาชิกบริการเหตุการณ์เดียวกันและตอบสนองโดยการปรับเปลี่ยนรูปแบบที่เกี่ยวข้อง เพิ่มเติมเกี่ยวกับเรื่องนี้ด้านล่าง

แต่ให้แน่ใจว่าจะยกเลิกการเป็นสมาชิกในการทำลายขององค์ประกอบหลัก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.