Avoiding redundant EventEmitters when transferring @Output to a child component

While working on a form component, I decided to separate the form action buttons into a child component. This led me to create two EventEmitter and handlers for the same action.

I'm wondering if there is a way to directly pass the 'onDiscard' event handler received in FormComponent to FormActionsComponent without having to create a new handler for it?

It would be great if I could avoid writing two event handlers and emitting the event twice.

FormComponent:

@Component({
  selector: 'app-form',
  template: `
        <form [formGroup]="nametagForm" (ngSubmit)="handleSubmit()">
            ...
            <app-form-actions (onDiscard)="handleDiscard()"></app-form-actions>
        </form>
    `,
  styleUrls: []
})
export class FormComponent implements OnInit {
  ...
  @Output()
  onDiscard = new EventEmitter<void>()

  handleDiscard(): void { this.onDiscard.emit() }
}

FormActionsComponent:

@Component({
  selector: 'app-form-actions',
  template: `
        <div class="form-actions">
            <button (click)="handleDiscard()" type="button">Discard</button>
            <button [disabled]="formControl.invalid" type="submit">Save</button>
        </div>
    `,
  styleUrls: []
})
export class FormActionsComponent implements OnInit {
  private formControl: FormGroup

  @Output()
  onDiscard = new EventEmitter<void>()

  constructor(private readonly rootFormGroup: FormGroupDirective) { }

  ngOnInit(): void {
    this.formControl = this.rootFormGroup.control
  }

  handleDiscard(): void { this.onDiscard.emit() }
}

Some Parent Component:

@Component({
  selector: 'app-parent',
  templateUrl: `
        <app-form ... (onDiscard)="handleDiscard()"></app-form>
    `,
  styleUrls: []
})
export class ParentComponent implements OnInit {    
  ...
  handleDiscard(): void { // do something ... }
}

Answer №1

It seems like a service would be helpful in achieving this task:

// form-handler.service.ts
@Injectable({ providedIn: 'root' })
export class FormHandlerService {
  private readonly _removed$ = new Subject<void>();
  readonly removed$ = this._removed$.asObservable();

  remove() {
    this._removed$.next();  
  }  
}

You can now inject the service into any component where it is needed and subscribe to the remove$ event.

For instance:

@Component({ ... })
export class MainComponent implements OnDestroy, OnInit {
  private readonly destroy$ = new Subject<void>();
  constructor(private readonly formHandlerService: FormHandlerService){}

  ngOnDestroy() { this.destroy$.next() }
  ngOnInit() {
    this.formHandlerService.removed$.pipe(
      takeUntil(this.destroy$)
    ).subscribe(() => {
       // Handling removal action
    })
  }
}

In the FormControlsComponent:

@Component({ ... })
export class FormControlsComponent {
  constructor(private readonly formHandlerService: FormHandlerService) {}

  handleRemove() { this.formHandlerService.remove(); }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for correctly saving an array to a file in node.js express using fs module

I have been attempting to write an array to a file using node.js and angular for assistance, you can refer to the provided code in this question. Whenever I send the array, the file displays: [object Object],... If I use JSON.stringify(myArr) to send my ...

SFDC error: argument list missing closing parenthesis

I encountered an issue that states: "Missing ) after argument list" This problem arises when I attempt to click on a custom button within SFDC. The purpose of this button is to initiate a specific case type in both our Internal and Community environme ...

"How to incorporate SortableJS into Ionic 3 Angular app with the help of the systemjs.config.js

I'm currently following the instructions on https://github.com/SortableJS/angular-sortablejs and I seem to be facing an issue with the systemjs.config.js file. My app is built using Ionic 3 and Angular 4. To address this, I created a script called sy ...

Add several converted links as variables in each section

The title may not be the clearest, but I am facing a challenge with an ecommerce site that has unmodifiable HTML. My goal is to include additional links for each product displayed on a page showcasing multiple products. Each link should be unique to its re ...

Guide on importing an ES6 package into an Express Typescript Project that is being utilized by a Vite React package

My goal is to efficiently share zod models and JS functions between the backend (Express & TS) and frontend (Vite React) using a shared library stored on a gcloud npm repository. Although the shared library works flawlessly on the frontend, I continue to e ...

Retrieve information using PHP with AJAX without revealing it on the screen

Is it feasible to fetch data using Ajax in PHP and store them in a JS variable without displaying it? I require this data for date manipulation but do not want to show it. When I attempted to merely return the data without echoing it, the Ajax data in JS ...

What is the best way to merge the results of several runs of an observable function

When working with Firestore, I need to retrieve multiple documents, each with a unique sourceAddressValue. This means for a list of N strings, I may need to fetch N documents. I attempted the following approach: getLocationAddresses(addresses: string[]) { ...

What steps do I need to take to share my Node JS application on my local area network (

I have a Node.js application running on my Ubuntu machine successfully, as I can access it through localhost:8080. However, other machines on the network are unable to reach it. CODE: const portNumber = 8080 let app = express() app.use(express.static(__d ...

Angular validation for password and confirmation password fields

I have been working on implementing password and confirm password validation within an angular project. I recently came across a helpful answer on this thread Confirm password validation in Angular 6 that I tried to follow. Unfortunately, I am encountering ...

How to include extra data in Angular Firebase user creation using the createUserWithEmailAndPassword

Currently, I am working on implementing the Firebase createUserWithEmailAndPassword method. However, I would like to include an additional field named 'name' in Cloud Firestore. Below is a snippet of my code: auth.service.ts SignUp(email: string ...

Using @carbon/react in conjunction with Next.js version 13 leads to unconventional styling

Here's what I did to set up my Next.js application: npx create-next-app@latest I then installed the necessary package using: npm i -S @carbon/react The global styles in app/globals.scss were customized with this code snippet: @use '@carbon/reac ...

Is your custom login form in Web2py not submitting properly?

My attempt to customize the login form for web2py has hit a roadblock. Despite adding the necessary fields and submit button, nothing seems to be happening. Here's what the code in the form's view looks like: {{include 'web2py_ajax.html&apo ...

Printing keys of objects in an array in AngularJS through iteration

Here is an array of objects that I am attempting to iterate in ng-repeat and print keys, but I am facing some challenges. $scope.directivesInfo = [ {"ngRepeat": {"enter": true, "leave": true, "move": true, "add": false, "remove": false}}, {"ngView ...

Trigger the activation of an input field upon clicking an image labeled "edit"

I am currently developing a website where administrators have access to a dashboard page that displays a list of users. I am looking to implement a feature that allows admins to change the roles of other users directly from the same table row. Below is th ...

Launching npm start does not automatically open a browser tab

I'm currently learning angularjs 2 and I'm eager to create my first application using the framework. Following the guidelines on their official website, I proceeded with all the steps outlined in this link. In step 6, I am required to run the com ...

Executing javascript functions from various HTML tags

The code snippet below is what I currently have: <script src="jquery-1.10.2.min.js"></script> <script> $('#year li').click(function() { var text = $(this).text(); //alert('text is ' + text); $.post("B.php" ...

Is it necessary for the error event of xmlhttprequest to include an error message?

Currently, I am in the process of developing an AJAX request within a Firefox extension. The following code snippet illustrates my approach: function GetMenu(){ var oReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(); ...

Issue encountered while trying to obtain user authorization_code from Microsoft Graph

I am encountering an issue with obtaining the Authorization code for the user. After the user logs in, I extract the user code from the URL and then use Ajax to fetch the access_token. However, during this process, I encounter the following error : AADS ...

Tomickigrzegorz Script Finder Predictive Search

Hey there, I recently tried out the autocomplete script created by tomickigrzegorz. Check it out here! It's been working smoothly for me, but I'm facing an issue with external link tags like https//google.com not functioning properly. Here is ...

How can I compel npm to resolve dependencies flatly?

I am working on a project where multiple frontends share a common library. The module dependencies for these projects are managed using npm. In the package.json file of each project, I specify: "dependencies": { "mylib": "file:../<...path...> ...