Search code examples
javascriptangulardevextreme-angular

Calling Angular 7 method from JavaScript


I am using the Angular version of DevExtreme PivotGrid. Here is my Code

import { Component, OnInit, ViewChild, HostListener } from '@angular/core';
import { Service, Sale } from './pivotgrid.service';

import PivotGridDataSource from 'devextreme/ui/pivot_grid/data_source';
import { DxPivotGridComponent } from 'devextreme-angular';
@Component({
  selector: 'app-pivotgridsample',
  templateUrl: './pivotgridsample.component.html',
  styleUrls: ['./pivotgridsample.component.scss'],
  providers: [Service]
})

export class PivotgridsampleComponent implements OnInit {
  pivotGridDataSource: any;
  drillDownDataSource: any;
  originalData: Sale[];

  @ViewChild("sales", { static: true }) salesPivotGrid: DxPivotGridComponent;

  constructor(private service: Service) {
    this.originalData = this.service.getSales();

    this.pivotGridDataSource = new PivotGridDataSource({
      fields: [{
        caption: "Region",
        width: 120,
        dataField: "region",
        area: "row"
      }, {
        caption: "City",
        dataField: "city",
        width: 150,
        area: "row"
      }, {
        dataField: "date",
        dataType: "date",
        area: "column"
      }, {
        groupName: "date",
        groupInterval: "year",
        expanded: true
      }, {
        groupName: "date",
        groupInterval: "month",
        visible: false
      }, {
        caption: "Total",
        dataField: "amount",
        dataType: "number",
        summaryType: "sum",
        format: "currency",
        area: "data"
      }, {
        caption: "Running Total",
        dataField: "amount",
        dataType: "number",
        summaryType: "sum",
        format: "currency",
        area: "data",
        runningTotal: "row",
        allowCrossGroupCalculation: true
      }],
      store: service.getSales()
    });
  }

  onPivotCellClick(e) {

    if (e.area == "data") {

      let cellValue = e.cell.value == null ? "" : e.cell.value;
      let cell = e.cellElement;

      this.drillDownDataSource = this.pivotGridDataSource.createDrillDownDataSource(e.cell);

      // Check if there is already input attched to cell
      if (cell.childNodes.length > 0) {

        // Clear Cell content
        cell.innerHTML = '';

        // Append Textbox
        cell.innerHTML = '<input type="text" class="editable" value="' + cellValue + '" style="width:100%;">'
        var textBox = cell.querySelector("input.editable");
        textBox.focus();

        this.drillDownDataSource.load();
        let groupData = this.drillDownDataSource._items;
        let oData = this.originalData;
        let pivotTable = this.salesPivotGrid.instance;


        textBox.onkeypress = function (event) {
          var keycode = (event.keyCode ? event.keyCode : event.which);
          if (keycode == '13') {
            var newValue = textBox.value;
            cell.innerHTML = "<span>" + parseInt(newValue) + "</span>";
            textBox.remove();

            console.log(oData);

            for (var i = 0; i < oData.length; i++) {
              for (var j = 0; j < groupData.length; j++) {
                if (oData[i].id == groupData[j].id) {
                  oData[i].amount = newValue / groupData.length;
                  //console.log(drillDownDataSource._items[i].amount);
                }
              }
            }

            this.setDataSource(oData)
            //pivotTable.option("store", oData);
            //pivotTable.dataSource.store = oData;
          }
          return true;
        }
      }
    }
  }

  setDataSource(data:any){
    alert('can be called');
  }

  ngOnInit() {
  }

}

Here, I'm using onPivotCellClick of PivotGrid to handle my custom requirements. Basically, I'm attaching an input to a grid cell for inline editing purpose and also I'm attaching a key-press event to it.

Since, It is in plain JavaScript I'm not able to call the Angular method (i.e. setDataSource) from my input keypress callback function written in JavaScript.

Is there any way I can do this?


Solution

  • This problem is not about plain JavaScript but scope of this in JavaScript.

    Declare a variable that references this and use the variable when call methods of the component inside the callback function.

    onPivotCellClick(e) {
      const that = this;
      ...
      textBox.onkeypress = function (event) {
        ...
        that.setDataSource(oData);
        ...
    

    Or you can use arrow function to use this keyword as you intended.

    onPivotCellClick(e) {
      textBox.onkeypress = (event) => {
        ...
        this.setDataSource(oData);
        ...