Tips for invoking both a typescript arrow function and a regular javascript function within one event

Is it possible to call both a JavaScript function and a TypeScript function from the same onClick event in a chart? I am new to TypeScript and Angular, so I'm not sure if this is achievable.

The issue at hand is that I need to invoke a JavaScript function to activate a bar in the chart and a TypeScript function to open a dialog in the Angular component.


    onClick: function(evt){

      console.log(this);//<-- returns chart

      bar: () => {console.log(this)}; //<-- attempting to reference the component here
      bar(); // <-- does not work

      //console.log(document.getElementById('myChart'));
  }

Let's take a look at the complete code snippet:


  public barChartOptions = {
    scaleShowVerticalLines: false,
    responsive: true,
    events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
    onHover: console.log('onHover'),

    onClick: function(evt){
      //console.log(evt); Mouse Event
      console.log(this);
      const getFirst = array => console.log(this);
      console.log(getFirst);
      //bar: () => {console.log(this)};
      //bar();
      //console.log(document.getElementById('myChart'));
  },
    scales: {
      xAxes: [{
        stacked: true
      }],
      yAxes: [{
        stacked: true
      }]
    },
    legend: {
      display: true,
      position: 'right'
    },
    tooltips: {
      enabled: true,
      mode: 'point'
    }
  };

Below is the HTML template:


  my-bar-dialog works!
  <div>
    <div style="display: block">
      <canvas baseChart
              id="myChart"
              [datasets]="barChartData"
              [labels]="barChartLabels"
              [options]="barChartOptions"
              [legend]="barChartLegend"
              [chartType]="barChartType">
      </canvas>
    </div>
  </div>

  <button mat-raised-button (click)="openDialog()">Pick one</button>
  <button (click)="openDialog()">Pick one</button>

In summary, there are two different instances of "this" being returned:


    onClick: function(evt){
      let that = this;
      let bar=()=> {console.log(that.this)};
      bar();

  },

    onClick : (evt, datasets) => {
      if(datasets.length > 0){
        console.log(this);
      }
    },

The first returns a chart, while the second returns the component. However, I require both within the same function to interact with Chart.js API functions as well as component functions.

Shown below is the code for the component:


import { Component, OnInit, Inject } from '@angular/core';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
import { BarChartService } from '../bar-chart.service';
import { barChartClass } from '../barChartClass';

declare var foo: Function;

@Component({
  selector: 'app-my-bar-dialog',
  templateUrl: './my-bar-dialog.component.html',
  styleUrls: ['./my-bar-dialog.component.css'],
})
export class MyBarDialogComponent implements OnInit {

  client: string;
  tenant: string;

  constructor(public dialog: MatDialog, private barChartService: BarChartService) {
    foo();
  }

  barChart: barChartClass;
  public barChartLabels: any;
  public barChartType: any;
  public barChartLegend: any;
  public barChartData: any;

  getBarChart(): void {
    this.barChartService.getMockBarChart().subscribe(
      barChart => this.barChart = barChart
    );
    this.barChartData = this.barChart.barChartData;
    this.barChartLabels = this.barChart.barChartLabels;
    this.barChartType = this.barChart.barChartType;
    this.barChartLegend = this.barChart.barChartLegend;
  }

  public barChartOptions = {
    scaleShowVerticalLines: false,
    responsive: true,
    events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
    onHover: console.log('onHover'),

    onClick: function(evt){
      let that = this;
      let bar=()=> {console.log(that.this)};
      bar();
  },

    scales: {
      xAxes: [{
        stacked: true
      }],
      yAxes: [{
        stacked: true
      }]
    },
    legend: {
      display: true,
      position: 'right'
    },
    tooltips: {
      enabled: true,
      mode: 'point'
    }
  };

  openDialog(): void {
    const dialogRef = this.dialog.open(DialogData, {
      width: '250px',
      data: {client: this.client, tenant: this.tenant}
    });

    dialogRef.afterClosed().subscribe(result => {
      console.log('The dialog was closed');
      this.client = result;
    });
  }

  ngOnInit() {
    this.getBarChart();
  }
}

@Component({
  selector: 'dialog-data',
  templateUrl: 'dialog-data.html',
  styleUrls: ['dialog-data.css']
})
export class DialogData {

  constructor(
    public dialogRef: MatDialogRef<DialogData>,
    @Inject(MAT_DIALOG_DATA) public data: DialogData) {}

  onNoClick(): void {
    this.dialogRef.close();
  }

}

Answer №1

In the function, the use of the bar and colon is an attempt to describe its type rather than declare it. To actually declare the function, follow this syntax:

onClick: function(evt) {

    console.log(this);//<-- returns chart

    let bar = () => { console.log(this) };
    bar();

    //console.log(document.getElementById('myChart'));
  }

If you wish to both describe and declare it, use this format instead:

  onClick: function(evt) {

    console.log(this);//<-- returns chart

    let bar: () => void = () => { console.log(this) }; //<-- here I try to get this as component
    bar(); // <--doesnt work

    //console.log(document.getElementById('myChart'));
  }

Answer №2

Prior to using the chart within your component, it is advisable to assign it to another variable like so:

var that=this

Next, in your chart code:

 onClick: function(evt){

      console.log(this);//<-- returns chart

   let   bar= () => {console.log(that)}; //<-- 'that' should reference your component
  
  }

Check out the Stackblitz demo here

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

execute script upon changes to the DOM of the embedded vendor component

Incorporating a vendor component into MyComponent. @Component({ selector: 'my-component', template: `<vendor-component></vendor-component>` }) export class MyComponent { constructor() { } } Looking to execute some jQuery ope ...

Setting the default dropdown option in Angular

For my latest question, I decided to utilize ng-init. However, upon loading the page, I noticed that there is a blank default option. When I click and select another option, the blank option disappears. How can I remove this initial blank option? Here is ...

Tips for executing the JetBrains WebStorm refactoring tool 'modify ES6 import' for an entire project

Following a project refactor, certain files were relocated to a different npm package, leading to changes in source files to re-export them from their new location (in order to streamline the migration process). Later on, I came across a helpful refactori ...

Utilizing ES6 Functions to Transform Objects into Arrays

Is there a way to convert a JavaScript object into an array using ECMAScript-6? Take, for instance: var inputObj = {a:'foo', b:[1,2,3], c:null, z:55}; The desired outcome would look like this: ['foo', [1,2,3], null, 55] The seque ...

Tips for including a header with Apollo Client in a React Native app

In my React Native application, here's how I set up the Apollo client with an upload link: My goal is to include a header with a token value that will be sent with every request. However, I've had trouble finding an example specifically for Reac ...

Jade, res.render, and res.write are essential tools for rendering

I am currently working on creating a simple FTP client in Node.js. Everything seems to be running smoothly, but I am facing difficulty in displaying the "singleFile.name" in my Jade template. app.post('/ftp/login', function(req, res){ ftp.ls(" ...

Adjust the specific data type to match its relevant category

Is there a method to alter literal types in TypeScript, for instance. type T1 = ""; type T2 = 1 I am interested in obtaining string for T1 and number for T2. Regarding collections, I am unsure, but I assume it would involve applying it to the generic typ ...

Javascript problem with closing the browser window in Selenium WebDriver

Here are a couple of inquiries: Firstly: Is there a method to initiate the browser on a specific URL (instead of about:blank) while also setting the history length to 0 when starting on that URL? Secondly: I suspect this question is related to the one me ...

What is the best way to dynamically update styleUrls or style properties in Angular?

One of my goals is to give users the ability to customize colors and certain styles within my Angular application. I am thinking about creating a structure like this: Structure: component-one   folder-with-css-files     style-for-component-1-fo ...

An uncaught runtime error has occurred: TypeError - subSector.map is not a valid function

I'm encountering a challenge when attempting to map through JSON data retrieved from a fictitious API. The process works smoothly when there is more than one data item, but I encounter an error when there is only a single object. Below is the code sn ...

assisting with the transition effect using CSS3, JS, or jQuery

I am looking to alter the background-image of this particular image when transitioning to another one from my images folder, similar to this example. Below is the code that I have: CSS .image { position: relative; overflow: hidden; -webkit-tr ...

Utilizing an Ajax request to fetch a JSON file via FTP, we must display a progress bar indicating the percentage of

Utilizing jQuery ajax to retrieve a file from an FTP server and wanting to display the loading percentage in a Progress loader. Previously, when using HTTP requests and XMLHttpRequest, the following code was effective: $.ajax({ xhr: function() { ...

Challenges with Angular observables

Struggling to make observables work has been quite the challenge for me lately. My code now resembles a chaotic battleground rather than the organized structure it once was. The dreaded "ERROR TypeError: Cannot read property 'map' of undefined" ...

Enhancing a React modal to enable user input for updating state variables

Is there a way to utilize user input from the page to dynamically create elements in a React.js application? In my app.js file, I have defined some constants at the beginning for mock data: const book1 = [ {id: uuid(), content: 'reflections&apos ...

The AJAX request cannot be sent until the previous request has completed

I've encountered an issue where my AJAX request gets stuck until the previous non-AJAX request is completed. On my webpage, I have a video playing using HTML5 and I'm trying to make an AJAX call to the server simultaneously. Here are the detail ...

Combining JS Tree and Datatables for Enhanced Functionality

I am facing a challenge on my webpage where I have two columns. The left column consists of a checkbox jstree, while the right column contains a table using datatables. Both the table rows and tree are loaded at the start. My goal is to display a row when ...

Undoing alterations to the user interface in Angular 2 after discontinuing bi-directional data binding

UPDATE: Including code for further clarification. client.component.ts import { Component } from "@angular/core"; import { ClientService } from "../services/client.service"; import { Client } from "../types/client"; @Component({ selector: "rpcs-client", ...

Adding additional functionalities to ng-blur within the controller: A step-by-step guide

I am seeking to enhance the functionality of ng-blur for all input and textarea fields by adding a new function. These elements already have an existing ng-blur defined in the HTML, and my goal is to incorporate a new function into this existing setup from ...

Submit a single data value to two separate models in JSON format using MongoDB

I recently developed a code with 2 essential functions: module.exports.registerAccount = (reqBody) => { let newAccount = new User({ firstName : reqBody.firstName, lastName : reqBody.lastName, email : reqBody.email, mobileNum : reqBody.m ...

Can you explain the process of implementing a conditional render with three parts in React?

Currently, I am attempting to implement a conditional render but encountering some issues. Is it achievable? location: `${props.off_campus_location ? ( `${props.off_campus_location}` ) : ( `${props.campus_location.name}` ) : ( `${props.location_type}` )}` ...