Executing COMPONENT method from SERVICE

2020-05-02 03:00发布

问题:

I'm trying to execute a Component method from a Service method. I saw these other 2 threads:

Link1 - How to call component method from service?

Link2 - Angular2 call a Component from a Service

But they show a method executed from the constructor.

I'm using on an Ionic app, the Ion-Select component(lot of selects) And for it I'm using a feature call Action Sheet which has a callback handler for every option chosen from the select.

The Action is on the service, and so the Handler call. But each select has an own method that need to be called from the ActionSheet. Thats my code now:

SELECT EXAMPLE

import { Component, EventEmitter, Input, Output } from '@angular/core';
import { ActionSheetService } from '../../services/action-sheet.service';

import { Type } from '../../models/general/type.model';

@Component({
    selector: 'type-select-component',
    templateUrl: 'type-select.component.html',
    providers: [ ActionSheetService ]
})
export class TypeSelectComponent {

    @Input() public types: Object[];
    @Output() public typeId: EventEmitter<number> = new EventEmitter<number>();

    public updatedItem: Type = new Type();
    private actionTitle: string = "What's Type"

    constructor( private actionSheetService: ActionSheetService ) { }

    //The Service should execute this method
    public updateSelectItem(id:number, type: Type): void{
        this.updatedItem = type;
        this.typeId.emit(id);
    }

    public presentActionSheet(): void {
//calling the service method passing options for the action sheet 
this.actionSheetService.presentActionSheet(this.actionTitle,this.types as Type[]);
        }
    }

ACTION-SHEET SERVICE

import { Injectable } from '@angular/core';
import { ActionSheetController } from 'ionic-angular'

@Injectable()
export class ActionSheetService {

constructor(private actionSheetCtrl: ActionSheetController) { }

public presentActionSheet(
    actionTitle: string, 
    items: any[]): void {

    let actionSheet = this.actionSheetCtrl.create({
        title: actionTitle
    });
    for (let i = 0; i < items.length; i++) {
        actionSheet.addButton({
            text: items[i].name,
            cssClass: items[i].css,
            icon: items[i].selectIcon,
            handler: () => {
//Here I should execute the method updateSelectItem from the component
                updateSelectItem(i, items[i]);
                console.log('Service ActionHandler');
            }
        });
    }
    actionSheet.addButton({ text: 'Cancel', 'role': 'cancel' });
    actionSheet.present();
    }
}

Why am I doing this way??? Well I could put an action sheet in each select...But then it'll break DRY

Any help guys?

回答1:

You can pass a callback to your service and set it as handler for your action sheets.

public presentActionSheet(
    actionTitle: string, 
    items: any[],
    callbackHandler:any): void {

    let actionSheet = this.actionSheetCtrl.create({
        title: actionTitle
    });
    for (let i = 0; i < items.length; i++) {
        actionSheet.addButton({
            text: items[i].name,
            cssClass: items[i].css,
            icon: items[i].selectIcon,
            handler: () => {
                callbackHandler(i, items[i]);//call the handler passed
                console.log('Service ActionHandler');
            }
        });
    }
    actionSheet.addButton({ text: 'Cancel', 'role': 'cancel' });
    actionSheet.present();
    }

In your component

public presentActionSheet(): void {
//calling the service method passing options for the action sheet 
this.actionSheetService.presentActionSheet(this.actionTitle,this.types as Type[],this.updateSelectItem.bind(this) );//send your component function. Do not forget to bind the context
        }