【问题标题】:angular-highcharts : click event cannot load function from "this" scopeangular-highcharts:点击事件无法从“this”范围加载函数
【发布时间】:2018-05-10 10:27:07
【问题描述】:

我正在使用 angular-highcharts (https://www.npmjs.com/package/angular-highcharts),我能够检测到事件,但似乎无法加载函数。

事件捕获是为了点击任何系列的点...

events: {
    click: function(event) {
        alert("Highcharts event click detected... Next action will be to load 'myFunction'.. check the console for error");
        this.myFunction();
    }
}

它应该加载“myFunction()”,这是一个简单的警报。

myFunction() {
    alert("myFunction executed");
}

相反,控制台日志中的错误是:

> ERROR TypeError: this.myFunction is not a function

这在“vanilla”Javascript 中可以正常工作,但在 angular-highcharts 中不行。

角度(不工作):

https://stackblitz.com/edit/angular-8v1obg

香草(工作):

http://jsfiddle.net/marty232/kkgygaya/3/

如何获取角度版本来加载函数?

更新
问:为什么我希望能够加载函数?
答: 当用户点击一个数据点时,我需要触发各种外部服务、更改变量、更新 HTML 等。所以,即使我的示例是访问单个函数,我也需要基本上能够访问“this”范围内的“任何”函数或对象(理想情况下,也可以访问其他范围)。希望这是有道理的。

【问题讨论】:

  • 什么时候出现这个错误
  • 问题可能是在执行您的点击处理程序时,对“this”的引用发生了变化。在您的香草示例中,您引用了调用范围内的函数,但您的“this”范围在角度示例中发生了变化,因此它找不到该函数。不过,我不确定如何正确解决此问题。

标签: angular highcharts


【解决方案1】:

问题似乎是在您的角度示例中执行点击事件时您正在失去您的范围。在执行时对this 的引用与您所期望的不同。在您的 vanilla 示例中,您引用的是同一范围内的函数。

一种解决方案可能是不将要执行的函数绑定到组件本身,而是将其创建为初始化 highcharts 的块内的局部变量。

init() {
  // create the function in the same scope so it does not have to rely on "this"
  var myFunction=()=> {
     alert("myFunction is now properly executed");
  }

  let chart = new Chart({
    ..
    plotOptions: {
      series: {
        lineWidth: 2,
        events: {
          click: function(event) {
            alert("Highcharts event click detected... Next action will be to load 'myFunction'.. check the console for error");
            myFunction();          }
        }
      },
    },
    ...
  });
  ...
}

然后问题是该函数不再存在于 init 块之外,因此您无法从其他任何地方调用它。然后问题是这是否有必要。

编辑

所以我尝试了一些棘手的事情,并且在某个地方可能有人想为此打我的脸,但是嘿,这只是一个建议。

我们可以做些什么来保持函数绑定到组件,所以你仍然可以从 HTML 中调用它,但也可以在图表点击事件中使用它,就是将它提供给你的 init()函数作为参数。我越想它,我就越觉得它脏得要命。这就是它的样子。

myFunction() {alert("myFunction executed");}

ngOnInit() {
  // transport the function
  this.init(this.myFunction);
}

init(myFunction) {
  // now it is untied from the "this" scope
  let chart = new Chart({
    chart: {
      type: 'line'
    },
    plotOptions: {
      series: {
        lineWidth: 2,
        events: {
          click: function(event) {
            alert("Highcharts event click detected... Next action will be to load 'myFunction'.. check the console for error");
            // use the variable instead of the private function
            myFunction();          }
        }
      },

    },
    ...
  });
  ...
}

最终,当从图表调用时,您将无法在函数内部执行与组件上下文相关的操作,例如更改变量或尝试访问私有服务。所以最终这取决于你想用它做什么。

编辑 2

也许这个更干净一些。我们不是提供没有作用域的函数,而是将整个作用域绑定到一个变量中。这通常只需设置一个变量,如var that=this

init() {
  // let's save the whole scope in a variable, so it is know to the functions scope
  let componentScope = this;

  let chart = new Chart({
    chart: {
      type: 'line'
    },
    plotOptions: {
      series: {
        lineWidth: 2,
        events: {
          click: function(event) {
            alert("Highcharts event click detected... Next action will be to load 'myFunction'.. check the console for error");
            // use the component scope here
            componentScope.myFunction();          }
        }
      },

    },
    ...
  });
  ...
}

我认为这应该可以解决问题。我认为保存整个范围意味着您还可以访问其中的所有其他内容,例如私有组件函数、变量、服务等。

【讨论】:

  • 感谢您的努力。我现在已经用推理更新了我的问题。我需要能够访问“this”范围(可能还有其他范围)中的任何内容。我已经尝试了您提出的答案,并且确实可以访问 myFuncion,但是我无法访问任何其他功能...参见分叉示例:stackblitz.com/edit/angular-sl2nbs
  • 我已经更新了我的答案并添加了一个新的解决方案,它可能比第一个更容易和更干净
  • 非常感谢 Benedikt,您的 Edit 2 似乎完全符合要求。我创建了一个新的演示,在这里使用您的解决方案,供其他人参考:stackblitz.com/edit/angular-x81pmv
猜你喜欢
  • 2016-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
相关资源
最近更新 更多