Is there a way to import external css files that only affects the shadow DOM? I am working with sass and creating the css files automatically, so any tricks using javascript imports can't be done.
Right now, what I have is:
static get template() {
return html`
<style>
:host {
display: block;
}
</style>
....
}
In Polymer 2, it was possible to do something like:
<dom-module id="my-app">
<link rel="stylesheet" href="style.css">
<template></template>
</dom-module>
Is there a Polymer 3 way of acheving the same thing?
You can use variables in html-tag, like this:
import { htmlLiteral } from '#polymer/polymer/lib/utils/html-tag.js';
import myCSS from "style.css";
let myCSSLiteral = htmlLiteral(myCSS);
...
class MyElement extends PolymerElement {
static get template() {
return html`<style>${myCSSLiteral}</style>...`;
...
}
...
}
Please note: You have to convert variable from string to a htmlLiteral for using it in html-tag, though I do not know why Polymer does not support raw string variable directlly. good luck!
this works great for me!
return html`
<link rel="stylesheet" href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css">
<style>
/* I had to put !important to override the css imported above. */
</style>
<divclass="blablabla"></div>
`;
Related
I want to create a reusable dialog in Vaadin 10. Therefore I thought of using the tag in vaadin-dialog. I created a html file containing the templated vaadin-dialog.
<dom-module id="show-sera-dialog">
<template>
<vaadin-dialog opened="opened">
<sera-field></sera-field>
<slot></slot>
</vaadin-dialog>
<template>
</dom-module>
And I try to use it like this.
<show-sera-dialog opened="{{showSera}}">
It worked!
</show-sera-dialog>
The dialog will be opened and the sera-field displayed, but the text is never displayed. Is there an error withing these lines? Am I using vaadin-dialog the wrong way?
PS:
It works with this button:
<dom-module id="one-shot-button">
<template>
<vaadin-button on-click="_disable" theme="raised primary" disabled={{disabled}}>
<slot></slot>
</vaadin-button>
</template>
<script>
class OneShotButton extends I18nMixin(Polymer.Element) {
static get is() {
return 'one-shot-button'
}
static get properties() {
return {
disabled: {type: Boolean, notify: true}
}
}
_disable() {
this.disabled = true;
this.onClick();
}
}
customElements.define(OneShotButton.is, OneShotButton);
</script>
You are putting a <slot> inside a <template>. Template means that web component will do whatever it needs when rendering it, e.g. by creating multiple instances like cells in grid, etc.
In this case vaadin-dialog teleports the content to the body, so as it escapes any stacking context. Thus it makes slots not work because they are not in the same DOM hierarchy.
One way to create a reusable dialog would be to create a component like this
<dom-module id="show-sera-dialog">
<template>
<vaadin-dialog opened={{opened}}>
<template>
[[text]]
</template>
</vaadin-dialog>
</template>
<script>
class ShowSeraDialog extends Polymer.Element {
static get is() { return 'show-sera-dialog'; }
static get properties() {
return {
"text" : String,
"opened" : Boolean
}
}
}
window.customElements.define(ShowSeraDialog.is, ShowSeraDialog);
</script>
</dom-module>
And use it like this
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="./show-sera-dialog.html">
<dom-module id="polymer-test-app">
<template>
<show-sera-dialog id="dialog1" text="It worked!"></show-sera-dialog>
<button on-click="showDialog">Show dialog</button>
</template>
<script>
class PolymerTestApp extends Polymer.Element {
static get is() { return 'polymer-test-app'; }
showDialog() {
this.$.dialog1.opened = true;
}
}
window.customElements.define(PolymerTestApp.is, PolymerTestApp);
</script>
</dom-module>
I am trying to get a basic Polymer element to work in IE 11, but I am getting errors it looks like due to the Polymer code not loading correctly or having syntax errors.
custom-element.html
<link rel="import" href="/node_modules/#polymer/polymer/polymer-element.html">
<script>
class CustomElement extends Polymer.Element {
static get is() {
return "custom-element";
}
constructor() {
super();
this.textContent = "I'm a custom-element.";
}
}
customElements.define(CustomElement.is, CustomElement);
</script>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script type="application/javascript" src="/node_modules/#webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="custom-element.html">
</head>
<body>
<custom-element></custom-element>
</body>
</html>
The console errors show as "Expected ':'" and "Syntax error" in files like /polymer/lib/utils/case-map.html.js and /polymer/lib/elements/dom-module.html.js.
Has anyone else gotten this to work in IE 11?
IE11 does not recognize this syntax for classes because ES6 spec:
https://kangax.github.io/compat-table/es6/
class foo {
static bar() {
//..code..
}
}
It only works with the ES5 way of doing it:
var foo = {};
foo.bar = function() {
// ..code..
}
Therefore you either need to use the Polymer 1.7+ Syntax which is:
Polymer({
is: 'custom-element',
ready: function(){this.textContent = "I'm a custom-element."}.
})
or use Babel as a pre-processor, to transpile all your ES6 code to ES2015.
I'm playing around with the Polymer Starter kit and am creating a nested custom element. I have an outer element that 'outputs' the inner element multiple times.
My issue is that the inner element (business-card) contains a <paper-material>. This element is not being affected by global styles. I know that Polymer adds a class of scoped-style to the element which ensures it can only affect the local DOM. Removing the scoped-style class in Dev Tools applies global styling.
How do I apply the styles from the standard <paper-element> to my nested element or include those same styles within my custom element.
Edit
It appears the my issue is that the styles within 'app-theme' are not applied to the internal element. I can get the desired outcome if I copy the <paper-element> styles, including media queries, plus follow the answer from #Zikes.
It seems against the modular nature of polymer to duplicate everything from an element when the element is already perfect. Am I missing something?
business-card.html
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-material/paper-material.html">
<dom-module id="business-card">
<style>
:host {
display: block;
}
</style>
<template>
<paper-material>
<content></content>
</paper-material>
</template>
</dom-module>
<script>
(function() {
Polymer({
is: 'business-card'
});
})();
</script>
Any help much appreciated
Polymer protects element internals from document styles and vice-versa. This is CSS scoping and it's a prominent feature of Web Components.
It can seem problematic in simple examples, but it's generally very beneficial to component reuse that component styles don't bash each other, and that document styles don't unintentionally foul up a component.
Polymer Starter Kit is not ideally set up for using app-theme.html in other scopes, but one thing you can do is copy the style rules you want to use into a CSS file, and then import that CSS file in your element code as below. The import and styles are used efficiently (e.g., the import is only loaded once, even if you use it in multiple elements).
<dom-module id="business-card">
<link rel="import" type="css" href="theme-styles.css">
<style>
:host {
display: block;
}
</style>
<template>
<paper-material>
<content></content>
</paper-material>
</template>
<script>
Polymer({
is: 'business-card'
});
</script>
</dom-module>
Live example: http://jsbin.com/hojajo/edit?html,output
If you'd like to apply the paper-material effects to your element directly, you can do so like this:
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../paper-styles/shadow.html">
<dom-module id="business-card">
<style>
:host {
display: block;
position: relative;
#apply(--shadow-transition);
}
:host([elevation="1"]) {
#apply(--shadow-elevation-2dp);
}
:host([elevation="2"]) {
#apply(--shadow-elevation-4dp);
}
:host([elevation="3"]) {
#apply(--shadow-elevation-6dp);
}
:host([elevation="4"]) {
#apply(--shadow-elevation-8dp);
}
:host([elevation="5"]) {
#apply(--shadow-elevation-16dp);
}
</style>
<template>
<content></content>
</template>
</dom-module>
<script>
Polymer({
is: 'business-card',
properties: {
/**
* The z-depth of this element, from 0-5. Setting to 0 will remove the
* shadow, and each increasing number greater than 0 will be "deeper"
* than the last.
*
* #attribute elevation
* #type number
* #default 1
*/
elevation: {
type: Number,
reflectToAttribute: true,
value: 1
},
/**
* Set this to true to animate the shadow when setting a new
* `elevation` value.
*
* #attribute animated
* #type boolean
* #default false
*/
animated: {
type: Boolean,
reflectToAttribute: true,
value: false
}
}
});
</script>
This is copied from the paper-material code itself: https://github.com/PolymerElements/paper-material/blob/master/paper-material.html
I'm trying to get a reference of outer HTML(index.html)'s div from the polymer dart class. I know I can query the reference of app_element.html's div by the following code:
shadowRoot.querySelector('#select_this')
However, if I were to get a reference of index.html's div (#select_this), how can I do that from app_element.dart class? Is this even possible? If not, how can I design the polymer elements so that it can access DOM of other HTML pages and not only the ones that bind that particular polymer element?
app_element.dart
#CustomTag('app-element')
class AppElement extends PolymerElement {
#override
void attached() {
var my_div = shadowRoot.querySelector('#select_this'); // contains app_element.html's #select_this div
}
}
index.html
<html>
<body>
<head>
<link rel="import" href="../lib/app_element.html">
</head>
<app-element></app-element>
<div id="select_this"></div> <!-- Not sure how to select this... -->
<script type="application/dart">export 'package:polymer/init.dart';</script>-->
<script src="packages/browser/dart.js"></script>
</body>
</html>
app_element.html
<!DOCTYPE html>
<polymer-element name='app-element'>
<div id="select_this"> <!-- selectable via: shadowRoot.querySelector('#select_this') -->
<script type="application/dart" src="app_element.dart"></script>
</polymer-element>
Use the documents querySelector instead:
import 'dart:html';
...
document.querySelector('#select_this');
You can get access to elements within other elements shadow DOM
// old
document.querySelector('* /deep/ #select_this');
// or new (probably not yet supported everywhere
document.querySelector('* >>> #select_this');
I tried to extend a <button>, but so far did not succeed.
What am I doing wrong. I'm using the Dart Editor+SDK 1.5.2
In pubspec.yaml the version for Polymer is set to:
polymer: ">=0.11.0 <0.12.0"
index.html
<!DOCTYPE html>
<html>
<head>
<!-- <script src="packages/web_components/platform.js"></script>
not necessary anymore with Polymer >= 0.14.0 -->
<script src="packages/web_components/dart_support.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Extended Button - Dart v1.5.2</title>
<!--Extended Button-->
<link rel="import" href="view/ext_button.html" />
</head>
<body>
<button is="ext-button">Test Button</button>
<script type="application/dart">export "package:polymer/init.dart";</script>
</body>
</html>
view/ext_button.dart
import "dart:html";
import "package:polymer/polymer.dart";
#CustomTag("ext-button")
class ExtButton extends ButtonElement {
ExtButton.created() : super.created();
factory ExtButton(){
onClick.listen(clicked);
}
void clicked(MouseEvent e){
print("Ext-Button clicked");
}
}
view/ext_button.html
<!DOCTYPE html>
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="ext-button" extends="button">
<template>
</template>
<script type="application/dart" src="ext_button.dart"></script>
</polymer-element>
So the code above does not work, but as soon as write it like below (just to validate the ext-button works) it tells me the following:
"web/index.html:20:7: custom element "ext-button" extends from "button", but this tag will not include the default properties of "button".
To fix this, either write this tag as <button is="ext-button"> or remove the "extends" attribute from the custom element declaration."
<ext-button>Test Button</ext-button>
So a little bit confused ;-) I think the fix is easy and simple - but I just don't see the problem ;-(
Just for further references, the two things above solved the problem.
Here are the updated parts, now it works.
view/ext_button.dart
import "dart:html";
import "package:polymer/polymer.dart";
#CustomTag("ext-button")
class ExtButton extends ButtonElement with Polymer {
ExtButton.created() : super.created()
{
polymerCreated();
onClick.listen(clicked);
}
void clicked(MouseEvent e){
print("Ext-Button clicked");
}
}
view/ext_button.html
<!DOCTYPE html>
<link rel="import" href="packages/polymer/polymer.html">
<polymer-element name="ext-button" extends="button">
<template>
<content></content>
</template>
<script type="application/dart" src="ext_button.dart"></script>
</polymer-element>
As far as I see, you are missing thwo things:
a call to polymerCreated() inside the custom elements constructor.
and extends ButtonElement with Polymer
There are already similar question. I'll look them up later when I have more time. Maybe you find them yourself in the meantime. Please add a comment with a link if you do.