2

I am trying out using custom elements. I want to use JS to create the elements and add them to the DOM. If I use this all in one file with a basic html page all works fine.

'use strict';
class FlashCard extends HTMLElement {
constructor(cardSet) {
    super();
    this.cardSet = cardSet;
    this.cardNumber = 0;
}
connectedCallback() {
    this.id = 'flashcard';
    this.style.cursor = 'pointer';
    this.render(this.cardSet);
    this.addEventListener('click', this.onClick);
}

render() {
    this.innerHTML = this.cardSet[this.cardNumber];
}

onClick() {
    let deckSize = this.cardSet.length;
    if (this.cardNumber === deckSize-1) {
        this.cardNumber = 0;
    } else {
        this.cardNumber++;
    };
    this.render();
}
}
customElements.define('flash-card', FlashCard);
document.addEventListener('DOMContentLoaded', function() {
let card = new FlashCard(['a', 'b', 'c', 'd']);
document.getElementsByTagName('body')[0].appendChild(card);
});

My problems start when I try to split the code into separate files.

'use strict';
export default class FlashCard extends HTMLElement {
    constructor(cardSet) {
        super();
        this.cardSet = cardSet;
        this.cardNumber = 0;
    }
    connectedCallback() {
        this.id = 'flashcard';
        this.style.cursor = 'pointer';
        this.render(this.cardSet);
        this.addEventListener('click', this.onClick);
    }

    render() {
        this.innerHTML = this.cardSet[this.cardNumber];
    }

    onClick() {
        let deckSize = this.cardSet.length;
        if (this.cardNumber === deckSize-1) {
            this.cardNumber = 0;
        } else {
            this.cardNumber++;
        };
        this.render();
    }
}
customElements.define('flash-card', FlashCard);

And In a separate file

import FlashCard from './flashcard';

    document.addEventListener('DOMContentLoaded', function() {
    let card = new FlashCard(['a', 'b', 'c', 'd']);
document.getElementsByTagName('body')[0].appendChild(card);
});

I then transpile the javascript because of the export/import using a npm script in the package.json file

"watch": "watchify elements/*.js -t babelify --plugins transform-es2015-classes 
-o js/bundle.js --debug --verbose",

The error I get in Chrome 55 is

Failed to construct 'HTMLElement': Please use the 'new' 
operator, this DOM object constructor cannot be called as a function.

So the transpiled code is trying to call the constructor method on HTMLElement object, but the method is not a function in this case.

My question is how do I split up my code into separate files as I am attempting to above but in a way the transpiler can interpret correctly?

1 Answer 1

2

You should try to use Reflect.construct() instead of super() in the constructor() method.

var self = Reflect.construct( HTMLElement, [], Flashcard )
self.cardSet = cardSet
...
return self

Also, you can try this plugin that is supposed to fix the issue (I didn't test it).

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you @Supersharp. The Reflect.construct instead of super(); didn't work for me. I got an error saying I needed a super();. But the plugin worked brilliantly. I am hugely grateful as I have been staring at it for hours.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.