Storing TypeScript functions as object properties within Angular 6

I am working on creating a simplified abstraction using Google charts. I have implemented a chartservice that will act as the abstraction layer, providing options and data-source while handling the rest (data retrieved from a REST API).

Below is the existing code snippet, which currently only caters to one specific case:

createCombo(comboBarLabels: String[], comboBarTypes: String[], options: any, element: any) {
    this.overviewService.getOverviewAggBarData().pipe(first()).subscribe(comboRequest => {
      for (const index of Object.keys(comboRequest.comboData)) {
        comboRequest.comboData[index].unshift(comboBarLabels[index]);
      }
      const data_array = [comboBarTypes, comboRequest.comboData[0],
        comboRequest.comboData[1], comboRequest.comboData[2]];
      google.charts.load('current', {'packages': ['corechart']});
      google.charts.setOnLoadCallback(() => {
        const data = ChartService.createDataTable(data_array);
        const chart = new google.visualization.ComboChart(element);
        chart.draw(data, options);
      });
    });
  }

My goal is to replace

this.overviewService.getOverviewAggBarData()
with a conditional function, somewhat like what can be done in Python:

def foo(a, b):  
    return a + b
a = foo
print(a(1, 2))  

Here is the desired pseudo-code:

createCombo(comboBarLabels: String[], comboBarTypes: String[], options: any, element: any, source: any) {
  if (source == "OverviewAggBar"){
    get_data = this.overviewService.getOverviewAggBarData;
  } else {
    get_data = this.overviewService.getOverviewPieData;
  }
  get_data().pipe(first()).subscribe(comboRequest => {
    for (const index of Object.keys(comboRequest.comboData)) {
      comboRequest.comboData[index].unshift(comboBarLabels[index]);
    }
    const data_array = [comboBarTypes, comboRequest.comboData[0],
      comboRequest.comboData[1], comboRequest.comboData[2]];
    google.charts.load('current', {'packages': ['corechart']});
    google.charts.setOnLoadCallback(() => {
      const data = ChartService.createDataTable(data_array);
      const chart = new google.visualization.ComboChart(element);
      chart.draw(data, options);
    });
  });
}

The objective behind this effort is to simplify the function call process. Abstracting this part away will enable us to create an even more versatile function. Any alternative solutions to achieve the same outcome are highly appreciated!

Issue resolved, presenting the updated code:

createCombo(comboBarLabels: String[], comboBarTypes: String[], options: any, element: any, source: string) {
    let getData: any;
    if (source === 'getAggData') {
      getData = this.overviewService.getOverviewAggBarData.bind(this);
    } else {
      getData = this.overviewService.getOverviewPieData.bind(this);
    }
    getData().pipe(first()).subscribe(comboRequest => {
      const data_array = [comboBarTypes];
      for (const index of Object.keys(comboRequest.comboData)) {
        comboRequest.comboData[index].unshift(comboBarLabels[index]);
        data_array.push(comboRequest.comboData[index]);
      }
      google.charts.load('current', {'packages': ['corechart']});
      google.charts.setOnLoadCallback(() => {
        const data = ChartService.createDataTable(data_array);
        const chart = new google.visualization.ComboChart(element);
        chart.draw(data, options);
      });
    });
  }

Answer №1

If you find yourself in a situation where you have numerous functions, consider establishing a "map" that connects the source string to each function. By doing so, you can easily incorporate additional functions into the map. Here's an example of how this could be implemented:

class YourClass {
    private mapFromSourceToFunction: { [key: string]: () => Observable<YourComboResponseType> } = {
        'getAggData': () => this.overviewService.getOverviewAggBarData(),
        'getPipeData': () => this.overviewService.getOverviewPieData(),
        'getSomethingElse': () => this.overviewService.getSomethingElse()
    };

    createCombo(comboBarLabels: String[], comboBarTypes: String[], options: any, element: any, source: string) {
        let getData = this.mapFromSourceToFunction[source];

        // getData().pipe ...
    }
}

Answer №2

It seems like you are on the right track already. JavaScript (and TypeScript) offers similar functionalities to achieve what you want. One area that needs improvement in your current code is the declaration of get_data variable. Here's how you can use a ternary operator for this purpose:

const get_data = source === "OverviewAggBar" ? this.overviewService.getOverviewAggBarData : this.overviewService.getOverviewPieData;

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

The error message "The type 'MouseEvent' is non-generic in TypeScript" popped up on the screen

Having created a custom button component, I encountered an issue when trying to handle the onClick event from outside the component. I specified the parameter type for the onClickCallback as MouseEvent<HTMLButtonElement, MouseEvent>, which is typical ...

Update the jQuery Get function to enable asynchronous behavior

I've recently been tasked with updating some older code to be asynchronous. The code in question is a jQuery GET function that looks like this: jQuery.get("my url", function(data){ //code here }); What steps can I take to convert this to an as ...

The lightbox feature seems to be malfunctioning, despite having successfully loaded jQuery

Struggling to activate lightbox on my gallery. Jquery is functioning as verified with an alert() in the documet.ready(). However, lightbox does not seem to be working properly. Only the links are operational. Below is a snippet of my code: <!DOCTYPE ht ...

The regex path matching issue in next.config.js is being caused by the pattern not being able to start with "?"

In my upcoming project, I attempted to utilize regex path matching in the next.config.js file as explained in the documentation. The goal was to match all routes except for one specific route by adding the regex ^(?!.*books). which successfully excludes an ...

Mismatch between generic types

When working with this code, I encounter a syntax error at m1 and m2. The error message states: Type 'T' is not assignable to Type 'boolean' or Type 'T' is not assignable to Type 'string' interface customMethod { ...

Consistently scaling the Embla carousel slides for a seamless presentation experience

In my current project, I am utilizing Embla Carousels and aiming to incorporate a smooth slide scaling effect as users scroll through. The idea is for slides to enlarge the closer they get to the left edge of the carousel container, then decrease in size r ...

Numerous points of interaction within ion-item

Within my ion-list, each ion-item contains a link to navigate to the next page. When tapping on an ion-item, it successfully navigates to the detail page. The problem arises when there is a button inside each ion-item that triggers an action. Tapping on t ...

Getting Errors When Retrieving Data with Apostrophe Symbol ' in Node.js

I am currently developing a Next.js API page to extract data from a series of URLs. Interestingly, the URLs containing an apostrophe character ' fail to return any data, while those without it work perfectly fine. Surprisingly, when I execute the same ...

What could be causing the primeng dialog to appear blank when conducting Jasmine tests on this Angular TypeScript application?

Having trouble testing a component due to rendering issues? Check out the code snippet below: import {ChangeDetectionStrategy, Component, EventEmitter, Input, Output} from '@angular/core'; @Component({ selector: 'app-help', cha ...

Switch up the Position of a Frame with jQuery

I'm attempting to cycle through an array of URLs in order to designate them as locations for a frame. The current setup I have can be found on this fiddle: var l = ['0', '1', '2', '3', '4', '5&ap ...

Is it possible to store a JWT token in local storage when working with Next.js?

We are considering using Next.js for our application, with a focus on client-side rendering for data fetching. The API we will be interacting with is external and requires authentication to access specific user dashboard content. While the homepage will ...

npm error: JSON input unexpectedly ended while parsing

Encountered an error when running ng new project-name in my Angular project. npm WARN deprecated [email protected]: CircularJSON is in maintenance only, flatted is its successor. npm ERR! Unexpected end of JSON input while parsing near '...: ...

Sort the observable data by a value returned from an API request

I am completely new to using RxJS and any assistance offered would be greatly appreciated! Within my component's HTML template, I am looking to create a radio button list. The values for this list are fetched from an observable using the async pipe. ...

Tips for inserting a button under a div when clicked

I am working on a layout where I have several div cards aligned side by side using the display: inline-block property. What I want to achieve is that when I click on a card, a button is added below the respective div. To accomplish this, I tried using jqu ...

The variable that contains a function is invoked, but the result is undefined

I'm having trouble with a function that should return John temp (2021) when called, but instead it's returning John undefined (undefined) const user = { username : 'John', type: 'temp', yearJoin: 2021, user ...

Angular: the xhrRequest is failing to be sent

I am facing an issue with a service function that handles an HTTP post request. The request does not get sent for some reason. However, when I add a subscription to the post method, the request is successfully executed. In other services that have the sam ...

Utilizing component data in Vue.js to configure the router-link attribute

Is there a way to pass component data in <router-link to="...">? Here's an example: var data = { files: [{ name: "test", path: "/test" }] }; var component = { data: function() { return data; ...

How do I activate the <li> tag using jQuery?

I am currently implementing pagination on my webpage using the following JavaScript code: var pagingList = $('<ul>', {class: 'pagination list-unstyled list-inline'}); ...

Is it possible for a node and @angular/cli based application to function without an internet connection?

As a newcomer to the world of angular/cli and node, I am eager to build an application using Angular and deploy it to an environment where all external communication is blocked by a firewall. In this restricted setting, even accessing search engines is imp ...

Issue with TypeScript problemMatcher "$tsc-watch" not actively monitoring files in VSCode

I'm attempting to avoid the necessity of using watch: true in my tsconfig.json setup. Despite utilizing VSCode's tasks with the default problem matcher $tsc-watch, I am encountering an issue where tsc is not running in watch mode during the buil ...