Transfer methods utilizing the `this` keyword from a component to a common service

In the development process, I am currently working on breaking down a large component that retrieves data from a selected record and loads it into a FormGroup using FormBuilder.

My goal is to divide this component into reusable services and child components.

One of the key functions in the component is responsible for adding a new row to a FormArray. At the moment, this function is specific to the component itself.

Now my question is how can I refactor this function so that it can be moved to a service or another solution where it can be used across multiple components?

I want to avoid duplicating the logic by reusing the same function, however, since the function relies on the 'this' keyword to access the current context, I'm not sure how to make it reusable in a service.

The code snippet below represents the function I'm looking to move into a reusable service, considering that there are other similar functions in the component that also use the 'this' keyword:

TS Component

constructor(
    private fb: FormBuilder
  ) { }

  /**
   * Add a new element to a form control array
   * @param {string} formCtrlArrayName name of the form control array
   * @param {string} valueToAdd element to add to the form control array
   */
  public onAddRow(formCtrlArrayName: string, valueToAdd: any) {
    this[formCtrlArrayName].push(this.fb.control(valueToAdd));
  }

HTML Component

<button mat-button attr.aria-label="Add Assigned To" matTooltip="Add Assigned To"
    (click)="onAddRow('AssignedTo', '', '')">
    <mat-icon>add_circle</mat-icon>
  </button>

Answer №1

Just a quick idea - but maybe something along these lines could do the trick:

// Here's some general code that can be reused in a service or similar
public addRow(formCtrlArray: any, valueToAdd: any): any { // Receive any type and return any type
  let myArray = <Array<any>>formCtrlArray;
  myArray.push(valueToAdd);
  return myArray;
}

Afterwards, you can simply call this function from your component, providing the appropriate parameters...

Answer №2

BlairHolmes' advice was instrumental in guiding me in the right direction. Additionally, I found a relevant article that may be of interest: here

Below is the solution I came up with:

Service

  constructor(
    private fb: FormBuilder
  ) { }

  /**
   * Add a new element to a form control array
   * @param {string} formGroup form group of the form control array
   * @param {string} formCtrlArrayName name of the form control array
   * @param {string} valueToAdd element to add to the form control array
   */
  public addRow(formGroup: any, formCtrlArrayName: string, valueToAdd: any) {
    let control = formGroup.controls[formCtrlArrayName];
    control.push(this.fb.control(valueToAdd));
  }

TS Component (a wrapper to call from the HTML component)

  constructor(
    private fb: FormBuilder
  ) { }

  /**
   * Add a new element to a form control array
   * @param {string} formCtrlArrayName name of the form control array
   * @param {string} valueToAdd element to add to the form control array
   */
  public onAddRow(formCtrlArrayName: string, valueToAdd: any) {
    this.uiService.addRow(this.itemForm, formCtrlArrayName, valueToAdd);
  }

HTML Component (unchanged)

<button mat-button attr.aria-label="Add Assigned To" matTooltip="Add Assigned To"
  (click)="onAddRow('AssignedTo', '')">
  <mat-icon>add_circle</mat-icon>
</button>

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

Enhancing Efficiency: Streamlining Editing in KendoUI Grid for Angular 2/4

According to the information provided on this link, it seems that batch editing of the kendo ui grid for angular 2/4 is currently unavailable. Is there anyone who has come up with a solution or workaround for this issue? ...

What is the best way to initialize a component only when its tag is set to *ngIf=true?

Update: After receiving a very helpful answer from Günter Zöchbauer that resolved my issue, I still have a lingering question about the correct approach for achieving the desired result. The context is provided below. With my custom tag on the parent ...

Is it possible to initiate a request action in both the constructor and ngOnInit method?

I am facing a situation where I need to trigger a request action from both the constructor and ngOnInit functions in order to load data. However, I have noticed that on the second call, one of the dispatch actions is not being invoked and the data remains ...

Having trouble with accessing properties like `d3.svg()`, `d3.scale()` and other features of d3js within an Angular 2 environment

Struggling to incorporate d3.js into angular2. Below is the command I used to install d3 in Angular2: npm install --save d3 install --save-dev @types/d3 This is how my package.json appears: { "name": "my-app", "version": "0.0.0", "license": "M ...

What is the best way to determine if a local storage key is not present?

By applying the if condition below, I can determine whether or not the local storage key exists: this.data = localStorage.getItem('education'); if(this.data) { console.log("Exists"); } To check for its non-existence using an if conditi ...

The ng2-chart library displays date in the form of a Unix timestamp

I have a date object imported from my database, but it is showing up as a Unix timestamp (-62101391858000). I know I can format the date using pipes like {{myDate | date:medium}}, however, I am using ng2-charts so I need to find a different solution. My ch ...

What is the reason for the compatibility issue between sass-loader and Angular?

One of my rules for dealing with sass is as follows: { test: /\.(scss|sass)$/, use: [ { loader: 'raw-loader'}, { loader: 'sass-loader', options: {data: sassConfiguration} } ], } typescript loader { ...

Validation of email forms in Angular 5

I have encountered a challenge that I need help with: Using Angular 5 - template driven form In my template, there is an input field with the type email. Here's an example: <input type="email" [(ngModel)]="model.email" #email="ngModel" email /> ...

Angular 2 property accessor designed similar to Linq style

Many times, we come across an array (IEnumerable) property where we need to extract specific values. In C#, we can achieve this by using the following code snippet: public AssetModel PromoImage { get { return Assets.FirstOrDefa ...

What's Going on with My Angular Dropdown Menu?

Snippet of HTML code: <li class="nav-item dropdown pe-3"> <a class="nav-link nav-profile d-flex align-items-center pe-0" (click)="toggleProfileMenu()"> <img src="assets/img/profile-img.jpg" alt=& ...

NextJS: Route Handler encountering Method Not Allowed (405) error when trying to redirect

Current NextJs version is 13.4.3 I have set up a route handler to capture POST requests. For more information on route handlers, please refer to the documentation at [https://nextjs.org/docs/app/building-your-application/routing/router-handlers] In this ...

Angular Material throws errors when there are missing dependencies

I encountered an issue while trying to set up angular material in my project: Uncaught TypeError: Object(...) is not a function at bidi.es5.js:87 at Object../node_modules/@angular/cdk/esm5/bidi.es5.js (bidi.es5.js:89) at webpack_requir ...

Error with Background component in Next.js-TypeScript when trying to change color on mouseover because Window is not defined

Within my Background component, there is a function that includes an SVG which changes color upon mouseover. While this functionality works fine, I encountered an error when hosting the project using Vercel - "ReferenceError: window is not defined." This i ...

Adding a dynamic click event in HTML using IONIC 4

I've created a function using Regex to detect URL links and replace them with a span tag. The replacement process is working fine, but I'm facing an issue where when I include (click)="myFunction()" in the span, it doesn't recognize the cli ...

When a service alias is provided in Angular 7, it disrupts the build execution process

After creating a service called MyService and its mocked version - MyServiceMock, I utilized the mock service in my unit tests until the backend is ready, providing and using the results from the mocked service. To avoid future code changes when the backe ...

Auth0 Angular - No routes found to match

I recently set up an angular application and integrated it with Auth0 by following two helpful tutorials: https://auth0.com/docs/quickstart/spa/angular2/01-login https://auth0.com/docs/quickstart/spa/angular2/02-calling-an-api Here is a brief overview o ...

Using getter functions and Visual Studio for TypeScript

In my TypeScript classes in Visual Studio, I have been implementing getter functions. I find that using getter functions helps to clean up my code, although there is one issue that I would like to address. class Foo { doWork(){ console.log(this.bar ...

Angular 5: Display a blank URL with the source until the variables are resolved

In my template, if I have: <img src="/somepath/{{user?.UserGuid}}.png" /> When user is not yet resolved, the ?. prevents evaluating UserGuid, resulting in: <img src="/somepath/.png" /> Is there a way to prevent this without using *ngIf or c ...

Is There a Comparable Feature to *ngIf in DevExtreme?

Currently, I am diving into the world of webapp development using DevExtreme. As a novice in coding, this is my first time exploring the functionalities of DevExtreme. Essentially, I am seeking guidance on how to display certain elements based on specific ...

The route information is not appearing on the screen

I am facing an issue with my application's route called home. The content on this route is not being displayed; instead, only the menu from app.component is shown. I believe I might be overlooking something obvious. Can someone assist me with this pro ...