Angular2 - Interaction between components using a service

后端 未结 3 1254
谎友^
谎友^ 2020-11-29 09:12

I have two component A and B, where component A contains a button. I wish when user click on this button, fire a function on component B


         


        
相关标签:
3条回答
  • 2020-11-29 09:21

    Angular Service

    You have to use a service to communicate between your two components.

    See https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

    Your service has a property event. So the component A can emit the event and the component B can subscribe to it.

    Use RxJS to emit and subscribe to your event.

    If my answer does not satisfy you. Please tell me and I will work on it.

    0 讨论(0)
  • 2020-11-29 09:28

    STOP USING SERVICES FOR COMPONENTS INTERACTION!!!

    Service is a stateless concept in programming, it can only rely on the input and other injected services to produce its output. Storing data inside service(although works) is counter-pattern (since your service is now stateful).

    You can achieve what you need with binding @Input() and @Output() of components:

    //main container html
    <A></A>
    <router-outlet (activate)="onRouterOutletActivate($event)"></router-outlet>
    
    //main container ts
    @ViewChild(ComponentA, {static: false}) a : ComponentA;
    onRouterOutletActivate(event: ContainerOfB): void {
        this.activeRouteComponent = event;
        // make sure doStuff method is defined public in ComponentB
        // clickOutput is an @Output() on ComponentA which propagates click event
        this.a.clickOutput.subscribe(() => this.activeRouteComponent.b.doStuff());
    }
    
    //ContainerOfB, the container that has B in it
    @ViewChild(ComponentB, {static: false}) b : ComponentB;
    
    //ComponentA html
    <button (click)="callback()">button</button>
    
    //ComponentA ts
    @Output() clickOutput: EventEmitter<void> = new EventEmitter<void>()
    callback() { this.clickOutput.emit(); }
    

    You would also achieve asynchronicity and reactiveness which is strongly emphasized by having rxjs in the core of Angular (whereas with service approach you won't).

    I get that sharing service for component communication is less complex than the above approach but just because it works it doesn't mean you should do it. If you're locked out of your Mercedes, what would you rather do: breaking the window glass and unlocking the door or calling the locksmith to come over and unlock it.

    p.s. Angular is dope hence the analogy(Mercedes)

    0 讨论(0)
  • 2020-11-29 09:38

    Shared service is a common way of communication between non-related components. Your components need to use a single instance of the service, so make sure it's provided at the root level.

    An example using the BehaviorSubject as a data delegate:

    Shared service:

    @Injectable()
    export class SharedService {
    
        isVisibleSource: BehaviorSubject<boolean> = new BehaviorSubject(false);
    
        constructor() { }
    }
    

    Component 1:

    export class Component1 {
    
        isVisible: boolean = false;
    
        constructor(private sharedService: SharedService) { }
    
        onClick(): void {
            this.isVisible = !this.isVisible;
            this.sharedService.isVisibleSource.next(this.isVisible);
        }
    }
    

    Component 2:

    export class Component2 {
    
        constructor(private sharedService: SharedService) { }
    
        ngOnInit() {
            this.sharedService.isVisibleSource.subscribe((isVisible: boolean) => {
                console.log('isVisible: ', isVisible); // => true/false
            });
        }
    }
    

    It is worth mentioning that BehaviorSubject upon a subscription returns the last value it holds, therefore the component from the example above will be updated with the most recent value immediately after the instantiation.

    BehaviorSubject also allows to get its most recent value without even subscribing to it:

    this.sharedService.isVisibleSource.getValue(); // => true/false
    
    0 讨论(0)
提交回复
热议问题