如何在Component B中实现并调用Component A的editRole()函数逻辑?
Let's fix this cross-component function implementation issue properly. The approach you're currently taking has a couple of key problems: storing a function name as a string won't let you trigger the actual function in Component B, and Angular doesn't process (click) bindings in dynamically generated HTML (it sanitizes those to prevent security risks).
Here are two clean, Angular-compliant solutions to achieve what you want:
Solution 1: Use @Output Event Emitter (Recommended)
This follows Angular's standard component communication pattern where the child component (Component A) emits an event, and the parent component (Component B) listens to it and runs its own logic.
Step 1: Update Component A
- Import required Angular modules:
import { Component, Output, EventEmitter, ElementRef, AfterViewInit } from '@angular/core';
- Define an event emitter and add logic to bind click events to your dynamic buttons:
@Component({ selector: 'app-component-a', // Your template and styles here }) export class ComponentA implements AfterViewInit { @Output() editClicked = new EventEmitter<void>(); constructor(private el: ElementRef) {} getActions(Dropup: boolean): string { return `<div class="dropdown ${Dropup ? 'dropup' : ''}"> <button class="m-portlet__nav-link btn m-btn m-btn--hover-accent m-btn--icon m-btn--icon-only m-btn--pill edit-action-btn" title="Edit"> <i class="flaticon-edit-1"></i> </button> <button class="m-portlet__nav-link btn m-btn m-btn--hover-danger m-btn--icon m-btn--icon-only m-btn--pill" title="Delete"> <i class="fa fa-trash-o"></i> </button> </div>`; } ngAfterViewInit() { this.bindEditButtonEvents(); } // Re-run this method if you re-render actions (e.g., after pagination or data refresh) bindEditButtonEvents() { const editButtons = this.el.nativeElement.querySelectorAll('.edit-action-btn'); editButtons.forEach(btn => { btn.addEventListener('click', () => { this.editClicked.emit(); }); }); } }
Step 2: Update Component B
- In Component B's template, listen to the
editClickedevent from Component A:
<app-component-a (editClicked)="editRole()"></app-component-a>
- Define your
editRole()function in Component B's TypeScript:
@Component({ selector: 'app-component-b', // Your template and styles here }) export class ComponentB { editRole() { // Your edit logic goes here! console.log('Edit role logic executed from Component B'); } }
Solution 2: Pass a Callback Function via @Input
If you prefer passing a direct callback from Component B to Component A, this approach works too.
Step 1: Update Component A
- Import required modules:
import { Component, Input, ElementRef, AfterViewInit } from '@angular/core';
- Define an input to accept the callback and bind it to the buttons:
@Component({ selector: 'app-component-a', // Your template and styles here }) export class ComponentA implements AfterViewInit { @Input() onEdit: () => void; constructor(private el: ElementRef) {} getActions(Dropup: boolean): string { return `<div class="dropdown ${Dropup ? 'dropup' : ''}"> <button class="m-portlet__nav-link btn m-btn m-btn--hover-accent m-btn--icon m-btn--icon-only m-btn--pill edit-action-btn" title="Edit"> <i class="flaticon-edit-1"></i> </button> <button class="m-portlet__nav-link btn m-btn m-btn--hover-danger m-btn--icon m-btn--icon-only m-btn--pill" title="Delete"> <i class="fa fa-trash-o"></i> </button> </div>`; } ngAfterViewInit() { this.bindEditButtonEvents(); } bindEditButtonEvents() { const editButtons = this.el.nativeElement.querySelectorAll('.edit-action-btn'); editButtons.forEach(btn => { btn.addEventListener('click', () => { if (this.onEdit) { this.onEdit(); } }); }); } }
Step 2: Update Component B
- Pass your
editRolefunction to Component A (bindthisto preserve the component context):
import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { ComponentA } from './component-a.component'; @Component({ selector: 'app-component-b', template: `<app-component-a #childComponent></app-component-a>` }) export class ComponentB implements AfterViewInit { @ViewChild('childComponent') child: ComponentA; ngAfterViewInit() { // Bind `this` to ensure the function uses Component B's context this.child.onEdit = this.editRole.bind(this); } editRole() { // Your edit logic here console.log('Edit role triggered from Component B'); } }
Key Notes:
- Why your original approach failed: Storing a function name as a string (
editFonction = "editRole()") doesn't create a reference to the actual function in Component B. Additionally, Angular sanitizes dynamically added HTML, so(click)bindings in your generated string won't be processed. - Re-binding events: If your
getActionsfunction runs multiple times (e.g., when table data refreshes), callbindEditButtonEvents()again to attach listeners to new buttons.
内容的提问来源于stack exchange,提问作者Tarek_MT

