2

I believe this issue is to do with the keyword "this" not being assigned to what i assume it is.

I am using Angular 5 and a WordCloud package. https://github.com/timdream/wordcloud2.js/blob/gh-pages/API.md

There is a click callback function which returns the individual string of the word clicked in a callback. When a user clicks the word i need it to call another function and show a modal.

component.ts

import { Component, OnInit, Input } from '@angular/core';
const WordCloud = require('wordcloud');

import { MatDialog, MAT_DIALOG_DATA } from '@angular/material';
import { TopWordsModalComponent } from './top-words-modal/top-words-modal.component';

@Component({
    selector: 'app-top-words',
    templateUrl: './top-words.component.html',
    styleUrls: ['./top-words.component.scss']
})

export class TopWordsComponent implements OnInit {

    @Input() report;
    categories: any = null;
    filterForm: FormGroup;

    constructor(private fb: FormBuilder, public modal: MatDialog) {

    }

    ngOnInit() {

        const all_words = this.report.activity.top_words;

        this.generateWordCloud(all_words);

    }

    generateWordCloud(words) {

        WordCloud(document.getElementById('word_cloud'), {

            list: words,
            click: function (data) {
                console.log(this);
                this.openModal(data);
            },
            classes: ['clickable']

        });
    }

    openModal(word) {

        this.modal.open(TopWordsModalComponent, {

            width: '1020px',
            data: { report: this.report, word: word }

        });

    }


}

However when it tries to call this.openModal() i get the following error:

core.js:1448 ERROR TypeError: this.openModal is not a function at Object.click (top-words.component.ts:79) at HTMLDivElement.wordcloudclick (wordcloud2.js:440) at ZoneDelegate.invokeTask (zone.js:421) at Object.onInvokeTask (core.js:4740) at ZoneDelegate.invokeTask (zone.js:420) at Zone.runTask (zone.js:188) at ZoneTask.invokeTask [as invoke] (zone.js:496) at invokeTask (zone.js:1517) at HTMLDivElement.globalZoneAwareCallback (zone.js:1543)

And the console.log gives the word object.

{list: Array(100), fontFamily: "Times, serif", fontWeight: "normal", color: ƒ, minSize: 0, …}

Can you see how it is referring to "object click" i believe the "this" property is assigned to the callback object and not my component so im not able to call another function.

What is the solution here?

FAISAL
  • 33,618
  • 10
  • 97
  • 105
Kay
  • 17,906
  • 63
  • 162
  • 270

1 Answers1

5

Use arrow function i.e. () => instead of the function keyword. A method with the function keyword has its own this context and hides the access to class properties/methods as opposed to arrow functions.

As described on the Mozilla Web Docs:

An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.

Change your code to following:

generateWordCloud(words) {
    WordCloud(document.getElementById('word_cloud'), {
        list: words,
        click: (data) => {
            console.log(this);
            this.openModal(data);
        },
        classes: ['clickable']
    });
}
FAISAL
  • 33,618
  • 10
  • 97
  • 105