I'm tinkering around with Polymer again and there is something I want to do but it doesn't work and the workaround looks so messy. I want to style an element but take advantage of Data Binding. Basically I try to do this:
<dom-module id="proto-element">
<template>
<style>
#wrapper{
width:{{pixels}};
background: #e1e1e1;
}
#bar{
width:80%;
}
</style>
<div id="wrapper">
<div id="bar" style$={{barStyle}}>I'm the bar! <b>{{test}}</b></div>
</div>
</template>
</dom-module>
<script>
Polymer({
is: "proto-element",
ready: function() {
this.pixels = "300px";
this.test = "Fear me!"
}
});
</script>
The text bound to this.test works flawlessley. But the moustache tags that are inside of style get ignored. Is there a simple solution to this? Because using the inline style$= syntax is super messy when you are working with multiple css rules and also you always need to concatinate a string for it to work if the value you want is obtained elsewhere. Any ideas on a nice clean solution?
I'm afraid what you want is (at least currently) not possible. Data-binding works only inside <template> tags, either a <template is="auto-binding"> or the template inside a <dom-module>.
In the <style> tag, data-binding simply won't work. You could try putting another <style> tag INSIDE the <template> tag (which is messy), but you still won't get the data-bound property to work, since the curly brackets {{...}} must be inside an individual tag and can't be (currently) surrounded by whitespaces (spaces, newlines, ...), see docs:
String concatenation is not supported inside a tag, and the tag can’t contain any whitespace ...
tl;dr: There are two issues that prevent you from achieving what you want: 1) Data-binding only works inside a template tag and 2) if you want to print out data-bound properties, they must be enclosed inside a html tag.
You could try a different approach:
ready: function () {
this.$.wrapper.style.width = '300px';
}
this.$ allows you to easily access any DOM element with an id attribute (for example your #wrapper, which is accessed as this.$.wrapper) and from there, you can set any other attribute of the element (this.$.wrapper.style.width in this case).
EDIT: Also, I just noticed that you've actually put <style> tag inside the <template>, which is not advised. Since Polymer 0.8, this is the recommended structure for a custom element:
<dom-module>
<style> ... </style>
<template> ... </template>
</dom-module>
<script> ... </script>
Check out the Overview and Migration guide.
EDIT 2: As of Polymer 1.1 the suggested element structure (as pointed out by Max Waterman) has been updated to:
<dom-module>
<template>
<style> ... </style>
...
</template>
<script> ... </script>
</dom-module>
Related
I need some templated markup inside my blazor component.
This is how I'd typically define it (and read it via script):
<script type="text/template" id="foo">
...
</script>
However that gives:
Script tags should not be placed inside components because they cannot be updated dynamically. To fix this, move the script tag to the 'index.html' file or another static location. (RZ9992)
How can I suppress RZ9992 just for that one code block?
UPDATE: no that supposed dupe is far more complicated that what I wanted here. People who want a template tag will get the same error, but for a different problem.
Found the answer here.
<script type="text/template" id="foo" suppress-error="BL9992">
...
</script>
But there's an even better way, which according to caniuse is widely supported now:
<template id="foo">
...
</template>
However, note that (probably due to a bug by design) the tag will be empty if it contains a component:
<template id="foo">
<MyComponent />
</template>
I want the css rules in my webcomponent to be global in my page, not only in this local dom.
<dom-module id="x-custom">
<template>
<style>
h1{
color: red;
}
<!-- I want not only this local h1 to be red but also all h1 in my page -->
</style>
<h1>Hello stackoverflow<h1>
</template>
<script>
Polymer({
is: 'x-custom'
});
</script>
</dom-module>
Any help?
Thanks
Here's an example on how you can do it. But this will work only in case of shady-dom it will fail for shadow-dom. For shadow dom one option is to bind color of h1 wherever to use it to same default CSS variable something like
h1{
color:var(--my-color,--default-color);
//or
color:var(--my-color,var(--default-color)); //if you are using polymer 1.7.
}
And then you can assign the value to --default-color in your app-theme or in index.html like
<style is="custom-style">
:root{ //you can use html instead of :root if you are using polymer 1.7
--default-color:red;
}
</style>
Second, option will be to create a shared-style and include it everywhere you use h1 tag.
Although not exactly what you are looking for, shared styles may be an option even though they will need to be explicitly included for all your components.
To share style declarations between elements, you can package a set of style declarations inside a element. In this section, a holding styles is called a style module for convenience.
https://www.polymer-project.org/1.0/docs/devguide/styling#style-modules
So I have been trying to put together a custom storage element with Polymer which uses the polymer-localforage element inside it. The local forage element requires that you set it's name attribute and so I thought that I could simply pass the "name" attribute or "id" attribute from my custom element over to the local forage element in my template, but it doesn't work. To make sure I wasn't doing something wrong I did a custom element which just inserts the "name" attribute of the root into the "name" attribute of a div inside the template tag but that doesn't work either.
<dom-module id="x-custom">
<template>
<div name="{{name}}">Hello {{name}}</div>
</template>
</dom-module>
and the script
Polymer({
is: 'x-custom',
properties:{
"name": {
type: String
}
}
});
if I use the element
<x-custom name="foo" />
What I then get is
<div class="style-scope x-custom">Hello foo</div>
No name attribute at all, not even a blank one.
How can I drop a template value into an attribute of a child element?
Try adding $ at the end of attributes as below.
<dom-module id="x-custom">
<template>
<div name$="{{name}}">Hello {{name}}</div>
</template>
</dom-module>
The Polymer docs refer to this as annotated attribute binding.
Question
Which method of placing the <script> tags is "best-practice?"
Inside the <dom-module>?
or
Outside the <dom-module>?
Also, please answer:
Why?
What is the source of your answer?
What downside risks are there by doing it the "wrong" way?
Polymer Starter Kit: OUTSIDE
In the Polymer Starter Kit, the my-list.html and my-greeting.html files place the <script> tag outside the <dom-module>.
Like this:
<dom-module>
<style>...</style>
<template>...</template>
<dom-module>
<script>...</script>
Other Experts: INSIDE
However, I have heard and seen several examples from Google employees and Google developers that suggest the <script> tags should go inside the <dom-module>.
Like this:
<dom-module>
<style>...</style>
<template>...</template>
<script>...</script>
<dom-module>
The correct answer is - it shouldn't matter. While the documentation is indeed as #Mowzer noted, this is just an example rather than a definition. At least some actual Polymer elements like e. g. iron-image have it outside dom-module.
The relationship between the dom-module and the object Polymer constructor defines is established through the 'is' property of the object passed to the Polymer constructor and the id attribute of the dom-module.
From Local DOM guide:
Give the <dom-module> an id attribute that matches its element’s is property and put a inside the <dom-module>. Polymer will automatically clone this template’s contents into the element’s local DOM.
As a side note, you can also successfully use <script src="external.js"></script> to separate the html from the JS - I'm just guessing this is one possible reason for this question. The only drawback to this (AFAIK) is that in this case a vulcanized version of your element will show incorrect (offset) code line numbers for JS errors.
Looks like <script> tags should go inside the <dom-module>.
Per this definition in the developer guide.
Element definition
<dom-module id="element-name">
<template>
<style>
/* CSS rules for your element */
</style>
<!-- local DOM for your element -->
<div>{{greeting}}</div> <!-- data bindings in local DOM -->
</template>
<script>
// element registration
Polymer({
is: "element-name",
// add properties and methods on the element's prototype
properties: {
// declare properties for the element's public API
greeting: {
type: String,
value: "Hello!"
}
}
});
</script>
</dom-module>
Let's say I have something like:
<code>
<polymer-element name'my-element'>
<template>
<div>{{label}}</div>
</template>
</polymer-element>
</code>
Would it be possible for me to simply declare my element this way:
<code>
<my-element label='name'></my-element>
</code>
What I'm doing doesn't seem to work. Is there a straightforward way to bind in the markup?
There are a few issues with what you posted, you are missing an '=' after 'name' in your polymer-element, and you have to either call Polymer to register my-element or include noscript attribute.
In general, if you construct your question in JsBin (or similar) you can make sure you've resolved such issues which otherwise obscure the nature of your question.
Bottom line is that you must make label a published property before Polymer will automatically connect it to attributes. You can make it published by including the name in the attributes attribute of the polymer-element, like this:
<polymer-element name="my-element" attributes="label" noscript>
http://jsbin.com/kizahi/1/edit
<my-element label="name"></my-element>
<polymer-element name="my-element" attributes="label" noscript>
<template>
<div>{{label}}</div>
</template>
</polymer-element>