5

I am trying to split a Polymer 3 component into separated files so for example:

import { html, PolymerElement } from '@polymer/polymer/polymer-element';

export default class TestSplit extends PolymerElement {
  static get template() {
    return html`
      <style>
        p {
          color: blue;
        }
      </style>

      <p>Hello from component</p>
    `;
  }
}

customElements.define('test-split', TestSplit);

would look like something like:

index.js:

import { PolymerElement, html } from '@polymer/polymer/polymer-element';

import css from './style.css';
import template from './template.html';

export default class TestSplit extends PolymerElement {
  static get template() {
    return html`
      <style>${css}</style>
      ${template}
    `;
  }
}

customElements.define('test-split', TestSplit);

style.css:

p {         
  color: blue;          
}

template.html:

<p>Hello from component</p>

Edit1:

I tried out the following code with the same template.html and style.css files:

import-test.js:

import { html, PolymerElement } from '@polymer/polymer/polymer-element';
import CssHtmlLoader from './cssHtmlLoader';

export default class ImportTest extends PolymerElement {
  static get template() {
    let htmlTemplate = CssHtmlLoader.prototype.getHtmlTemplate('template.html');
      console.log(htmlTemplate)
      return htmlTemplate.then(function (file) {
        return html`
          <link rel="stylesheet" href="style.css"> 
          ${file}
        `;
      });  
    }
  }
}

customElements.define('import-test', ImportTest);

I am getting the right file from the promise: enter image description here

But I also get the following errors: enter image description here

Is there any idea what is wrong with the code?

Mike Poole
  • 1,958
  • 5
  • 29
  • 41
Tibor Fekete
  • 199
  • 14

2 Answers2

1

I think, the way you want to import the css and html file, isn't possible. They are simple css/html files. They don't provide any module to export these files.

Only exported javascript modules can be imported.

I don't think there is any way to import a css file in js:

import css from './style.css'; // css can't be imported this way.

Instead You can make a service for getting you these files:

Let's say,

Updated:

------------------------------------------------------------Working copy------------------------------------------------------------------

template.service.js :

export class TemplateService {

  xhrCall(url) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      xhr.open("GET", url);
      xhr.onload = () => resolve(xhr.responseText);
      xhr.onerror = () => reject(xhr.statusText);
      xhr.send();
    });
  }
  // As of now css is not dynamically included
  /*
  getCssTemplate(url) {
    return this.xhrCall(url);
  }
  */
  getHtmlTemplate(url) {
    return this.xhrCall(url);
  }

}

my-view1.html :

<div class="card">
  <div class="circle">1</div>
  <h1>View One</h1>
  <p>Ut labores minimum atomorum pro. Laudem tibique ut has.</p>
  <p>Lorem ipsum dolor sit amet, per in nusquam nominavi periculis, sit elit oportere ea.Lorem ipsum dolor sit amet, per in nusquam nominavi periculis, sit elit oportere ea.Cu mei vide viris gloriatur, at populo eripuit sit.</p>
</div>

my-view.html :

import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import './shared-styles.js';

import { TemplateService } from './services/template.service.js';

class MyView1 extends PolymerElement {

  constructor() {
    super();
    this.tpl = new TemplateService();
    this.getView();  // <---------------call getView in the constructor.
  }

  static get template() {
    return html `<style include="shared-styles">
    :host {
      display: block;
      padding: 10px;
    }
    </style>
    `;
  }

  getView() {
    let template$ = this.tpl.getHtmlTemplate('src/templates/html/my-view1.html');
    // get the promise in a var above.
    template$.then(file => {
      let wrapperDiv = document.createElement('div'); // create a node
      wrapperDiv.innerHTML = file; // push the contents

      this._attachDom(wrapperDiv); // Attach the DOM to component's custom element**
    });
  }

}
window.customElements.define('my-view1', MyView1);
Jai
  • 74,255
  • 12
  • 74
  • 103
  • Hi, I tried out your solution but I got a few errors. I added the results to the edit section. I updated the post for more information. Also, I figured out that you can load css file with the in the return html. – Tibor Fekete Nov 30 '18 at 11:05
  • Today, i just tried to do this as suggested and found similar issues. Will update when i get any success. – Jai Nov 30 '18 at 12:49
  • 1
    @TiborFekete, i just updated for loading the view in the page. I just let the inline style as is for now because it includes some styling. Will also update you on the css part too. **As of now** This is a working copy. – Jai Dec 04 '18 at 10:41
  • Hi thank you :D I also figured something similar out I will create an answer the only problem with this method is that you are not able to bind properties to the html template – Tibor Fekete Dec 04 '18 at 13:21
0

So I tried the following component:

import-test.js

import { html, PolymerElement } from '@polymer/polymer/polymer-element';
import {htmlLiteral} from '@polymer/polymer/lib/utils/html-tag.js';
import CssHtmlLoader from './cssHtmlLoader';

export default class ImportTest extends PolymerElement {

  static get properties() {
    return {
      htmlTemplate:{
        type:String,
        notify:true,
        reflectToAttribute: true
      },
      helloWorld:{
        type:String,
        notify:true,
        reflectToAttribute: true,
        value: 'auto'
      }
    }
  }

  constructor(){
    super();
    var that = this;
    this.attachShadow({mode: 'open'});
    console.log(this.shadowRoot);
    this.htmlTemplate = CssHtmlLoader.prototype.getHtmlTemplate('templaten.html');
    this.htmlTemplate.then((template) => {
      console.log(that);
      that.shadowRoot.innerHTML = template
    });
  }
}

customElements.define('import-test', ImportTest);

with the following html and css template:

style.css:

p {
    color: blue;
}

template.html:

 link rel="stylesheet" href="style.css"> 
 <p>Hello from template [[helloWorld]]</p>

and this was my output:

Hello PolymerImportTest-app!
Hello from template [[helloWorld]](this is blue so the css import works)

so my problem was that I was not able to bind properties to the html template.

And the solution for that was to put the html template into a separate javascript file and from there I was able to export it and use it in the custom component(with the propertie binding working).

Here is my solution:

import-test.js:

import { html, PolymerElement } from '@polymer/polymer/polymer-element';
import {template} from './template';

export default class ImportTest extends PolymerElement {

  static get properties() {
    return {
      helloWorld:{
        type:String,
        notify:true,
        reflectToAttribute: true,
        value: 'auto'
      }
    }
  }

  constructor(){
    super();
  }

  static get template() {
    return template;
  }

}

customElements.define('import-test', ImportTest);

template.js:

import {html} from '@polymer/polymer/polymer-element';

export const template=html`
<link rel="stylesheet" href="/src/PolymerImportTest-app/style.css">
<p>Hello from template [[helloWorld]]</p>
`;

style.css:

p {
    color: blue;
}

And the output:

Hello PolymerImportTest-app!
Hello from template auto(blue and the property is correctly attached)
Tibor Fekete
  • 199
  • 14