2

I have created two web components that live in separate files. When I try to reference one in the other using an import I get an error Uncaught SyntaxError: Unexpected token '-'

My code

File1

class element1 extends HTMLElement {
 constructor() {
        super();
        const li = document.createElement('li');
        this.shadowRoot.append(li);        
    }
}

customElements.define('my-element1', element1);

File 2

import {my-element1} from ".element1.js"

class element2 extends HTMLElement {
 constructor() {
        super();
        const ol = document.createElement('ol');
        ol.appendChild(document.createElement('my-element1'));
        this.shadowRoot.append(ol);        
    }
}

customElements.define('my-element2', element2);

2 Answers2

0

Why you want to use web components and coupling the components using imports?. If you use web components is to have independants components. If you add an import, the two components there will be always coupled.

You can check this answer which is clearer.

The best way to comunicate between elements is using events. Check this other

By the way, here you don't need events, because your components are defined, so you only need to create a document with the component name like this:

class element1 extends HTMLElement {
 constructor() {
        super();
        const shadowRoot = this.attachShadow({ mode: 'open' }); 
        shadowRoot.append("Hello from Component1");      
    }
}

customElements.define('my-element1', element1);

class element2 extends HTMLElement {
 constructor() {
        super();
        const element1 = document.createElement('my-element1');
        const shadowRoot = this.attachShadow({ mode: 'open' }); 
        shadowRoot.append("Hello from Component2, let me add Component1...")
        shadowRoot.append(document.createElement('br'))
        shadowRoot.append(element1);        
    }
}

customElements.define('my-element2', element2);
<html>
<body>
<my-element2></my-element2>
</body>
</html>

Note how in the DOM only my-element2 is called. And into the component, the number 1 is added.

Then you can achieve your goal playing with this, creating component1 from component2.

J.F.
  • 13,927
  • 9
  • 27
  • 65
  • 1
    Se [this](https://dev.to/dannyengelman/web-component-102-the-5-lessons-after-learning-web-components-101-h9p) Dev.to post for writing the above code shorter – Danny '365CSI' Engelman Oct 19 '21 at 18:35
  • Thank you for your response. Most web component use other components. For example: extending them or adding them to the Shadow Dom. Just because a Web Component is not a build in UI control doesn't make it different. –  Oct 20 '21 at 18:03
  • You example works because both your components are in the same file. Mine are in different files. I was able to get it to work by referencing both files in the HTML page. `` But it would be nicer to use an import because the end user would not need to have knowledge of the interworking of the component. As well, bundling applications would be able to identify the dependencies. –  Oct 20 '21 at 18:03
0

my-element1 isn't a valid JavaScript identifier and File1 isn't exporting anything. If you want to import specific symbols you have to first export them.

File 1

export class Element1 extends HTMLElement {
}

File 2

import {Element1} from "./element1.js"

The only reason you would import an component's JavaScript class though is if you need a handle to it. For example you could import the class and define the custom element in the second file.

File 1

export class Element1 extends HTMLElement {
}

File 2

import {Element1} from "./element1.js"

customElements.define('my-element1', Element1);

This is not a recommended pattern though as it gets complicated. If you want to add a third file that also depends on element1, my-element1 can only be defined once.

You can keep the code you currently have and make it work by importing file 1 without any symbols. customElements.define makes defined custom elements globally available so you have to make sure the component is loaded when you plan on using it but you don't need to import the class explicitly.

File 1

class Element1 extends HTMLElement {
}

customElements.define('my-element1', Element1);

File 2

import "./element1.js"

class Element2 extends HTMLElement {
}

customElements.define('my-element2', Element2);

Note that relative file imports in the same directory typically start with ./ and JavaScript class names typical start with capital letters.

abraham
  • 46,583
  • 10
  • 100
  • 152
  • Thank you for your input. Web components have to have a - in the name per the standard. As I mentioned in my comment above, I am able to use the component after referencing it in my HTML file; however, I rather use an import in the component file to streamline the code. I am just not sure if that is possible yet. –  Oct 21 '21 at 15:26
  • The `-` requirement is for the element tag name (`'my-element1'`) and used in HTML. It is different from the JavaScript class (`element1`) for the custom element. You can't `import` the tag name in JavaScript. The last example in my answer is what you want to do. – abraham Oct 21 '21 at 16:10