Polymer Inconsistent data with multiple component instances - polymer

I am using mp-slider (polymer 2.0) but needed the caption to be a link. I added the property sliderLink (as shown below) Everything seemed to be working except that the URL value for all instances is the value for the last instance. For example, if my links are google.com/1 google.com/2 yahoo.com/1 the links on all slides are yahoo.com/1
To address this I added value: function() { return []; } and I tried a few version of the syntax with no change in my results.
The oddity to me is that with three uses of the property, One instance has the correct value and the other two do not.
<link rel="import" href="../polymer/polymer.html">
<dom-module id="mp-caption">
<template>
<style>
#caption {
width: 100%;
background: var(--caption-background);
padding: 5px 20px;
position: absolute;
bottom: 0;
box-sizing: border-box;
transition: all 2s linear;
}
#caption h3, #caption p { color: var(--white-color) }
#caption h3 {
font-size: 20px;
margin: 10px 0;
padding: 0
}
#caption p {
font-size: 14px;
margin: 5px;
padding: 5px 0
}
</style>
<template is="dom-if" if="{{sliderLink}}">
<div id="caption">
<h3><a href={{sliderLink}}>{{sliderHeader}}</a></h3><!-- incorrect value for sliderLink here -->
<p><a href={{sliderLink}}>{{sliderContent}}</a></p><!-- incorrect value for sliderLink here -->
<p>{{sliderLink}}</p> <!-- correct value for sliderLink here -->
</div>
</template>
<template is="dom-if" if="{{!sliderLink}}">
<div id="caption">
<h3>{{sliderHeader}}</h3>
<p>{{sliderContent}}</p>
</div>
</template>
</template>
<script>
class mpCaption extends Polymer.Element {
static get is() {
return 'mp-caption'
}
static get properties() {
return {
sliderHeader: String,
sliderContent: String,
sliderLink: {String, value: function() { return []; }},
}
}
}
customElements.define(mpCaption.is, mpCaption);
</script>
</dom-module>
The only difference between the three uses is that the last one is not linked. Is this a bug, or am I missing something needed to make these properties URLs?
Thank you

Try binding to the href attribute instead of the property:
<a href$={{sliderLink}}>
For more info see the Polymer docs on binding to native HTML elements.

As Kate Jeffreys told you you should use attribute binding:
<a href$="{{sliderLink}}"></a>
I don't know how are you passing the value of each property but your example works without any problem.
I had to remove the position: absolute so I could see each caption without seeing it one on top of the other.
Another thing I have changed was the property sliderLink, you returned an empty array but doesn't make sense in a property of type String.
Here you can see the code: mp-caption code
Here you can check out the demo: mp-caption demo

Related

vaadin combobox load wrong custom style

In my polymer project , i use a vaadin-combobox in two page like this:
- page1: i create a custom combobox style file and import to my page:
<link rel="import" href="../elements/base/vaadin-text-field-custom-radius-theme.html">
content of this file:
<dom-module id="vaadin-text-field-custom-radius-theme" theme-for="vaadin-text-field">
<template>
<style>
[part="input-field"] {
border-radius: 2px;
background-color: white;
border: 1px solid #808080;
height: 100%;
font-family: "Roboto", sans-serif !important;
color: #4c4c4c !important;
padding-left: 10px;
font-size: 14px;
box-sizing: border-box;
max-height: 100%;
background-color: transparent;
background-image: none !important;
}
[part="value"] {
border: 0px !important;
box-shadow: none !important;
height: 100%;
box-sizing: border-box;
max-height: 100%;
background-color: transparent;
text-align: var(--cmb-align,left);
}
.vaadin-text-field {
height: 100%;
box-sizing: border-box;
max-height: 100%;
}
.vaadin-text-field-container {
height: 100%;
box-sizing: border-box;
max-height: 100%;
}
#media(max-width:1024px){
[part="input-field"] {
font-size: 12px !important;
padding-left: 5px;
}
[part="value"] {
font-size: 12px !important;
}
}
</style>
</template>
In page2 ,I have another custom style file with some other css properties.
I use
this.set('route.path',"/page2")
to redirect from page1 to page2 and then use
this.set('route.path',"/page1")
in page2 to return page1.
At this time my combobox in page1 is styled by css defined in custom file that i have imported to page 2 ( while i expected it's still styled by css in vaadin-text-field-custom-radius-theme.html").
Can some one tell me why?
p/s:I tried implement the suggestion of Anton Platonov, but i found that if my page 2 don't import any custom style file, When i return from page2 to page1, the default style of vaadin-text-field that defined in ..\bower_components\vaadin-text-field\vaadin-text-field.html is used for my combobox instead of my vaadin-text-field-custom-radius-theme.html.
If i remove style default in vaadin-text-field.html, my combobox revice css from browser's default style, still not my vaadin-text-field-custom-radius-theme.html.
It's treated like my vaadin-text-field-custom-radius-theme no longer exists.
And if i refesh my page 1, everything become normal.
this is my combobox code:
<vaadin-combo-box-light style="width:100%;height:30px" id="cmdCompanyName" class="fix-size combobox" label="" allow-custom-value items='[[companies]]'
value="" item-label-path="name" item-value-path="id" attr-for-selected="id" on-keyup="searchData"
on-custom-value-set="searchData2" on-value-changed="searchData2">
<vaadin-text-field style="width:100%;height:30px;" class="cmb-text-field" maxlength="150">
<iron-icon class="prefix" icon="icons:search" slot="prefix"></iron-icon>
<iron-icon class="suffix toggle-button" slot="suffix" icon="icons:expand-more"></iron-icon>
</vaadin-text-field>
</vaadin-combo-box-light>
I assume, your project is a Single Page Application, and you use <app-route>/<iron-pages> or a similar routing. This way the browser actually uses a single real document, which is then manipulated to achieve "pages" and navigation.
Due to technical limitations, theme style modules for Vaadin components are not dynamic in the way you expect. Once themes and components are loaded and initialised, their styles become memoized in the classes of their corresponding components.
Suppose you load "page2" first. After loading, <vaadin-text-field> memoizes its styles, and more theme modules can be applied. That is why when you navigate to "page1", <vaadin-text-field> will continue using the memoized style from "page2".
This means, you have to use same set styles in all the instances of, e. g.,
<vaadin-text-field>, in the document. Therefore, you have to use other means to make them look differently, instead of swapping styles. Here are some options.
Scoping :host() selectors
Prefix all the custom theme styles with a scoping :host() selector, for example:
<dom-module id="my-text-field" theme-for="vaadin-text-field">
<template>
<style>
:host(.no-radius) [part="input-field"] {
border-radius: 0;
}
</style>
</template>
</dom-module>
Then use in the html:
<h3>Default appearance</h3>
<vaadin-text-field></vaadin-text-field>
<h3>No-radius class</h3>
<vaadin-text-field class="no-radius"></vaadin-text-field>
Custom CSS properties
Define a custom CSS property in the <vaadin-text-field>’s parent DOM scope, e. g., in a page component:
<dom-module id="page-1">
<template>
<style>
:host {
--custom-radius: 4px;
}
</style>
<vaadin-text-field></vaadin-text-field>
</template>
</dom-module>
<script>
Polymer({is: 'page-1'});
</script>
You can also define some other value for the main document scope:
<custom-style>
<style>
html {
--custom-radius: 0;
}
</style>
</custom-style>
Use the defined custom CSS property in the theme style module for <vaadin-text-field>:
<dom-module id="my-text-field" theme-for="vaadin-text-field">
<template>
<style>
[part="input-field"] {
border-radius: var(--custom-radius);
}
</style>
</template>
</dom-module>
Then see the results:
<h3>Main document appearance:</h3>
<vaadin-text-field></vaadin-text-field>
<h3>Page 1 appearance:</h3>
<page-1></page-1>
See also: https://github.com/vaadin/vaadin-themable-mixin/wiki/4.-Scoping-Styles-in-a-Theme-Module

Make iron-icon bigger in paper-fab

I am using polymer and iron icons, my questio is: Can you make the iron icons while they are in a paper-fab:
my code:
<paper-fab id="add" icon="list" on-click="addingPersonnel"></paper-fab>
The icon is relativly small in comparison with the paper-fab.
I can see two possibilities.
The first one maybe you won't like it but it will remove the effect of a small icon, would be to use the attribute mini on the paper-fab :
<paper-fab mini id="add" icon="list" on-click="addingPersonnel"></paper-fab>
The second solution is to change the size of the icon in CSS as below :
paper-fab {
padding: 0;
--paper-fab-iron-icon: {
height: 30px;
width: 30px;
};
}
The padding is blocking the icon to go bigger than its current size so we will set it to 0.
And then using the mixin --paper-fab-iron-icon you can set the height and width of your icon.
The complete code will be :
<dom-module id="os-test">
<template>
<style>
paper-fab#add {
padding: 0;
--paper-fab-iron-icon: {
height: 40px;
width: 40px;
};
}
</style>
<paper-fab id="add" icon="list"></paper-fab>
</template>
</dom-module>
<script>
class OsTestElement extends Polymer.Element {
static get is() {
return 'os-test';
}
}
window.customElements.define(OsTestElement.is, OsTestElement);
</script>

Polymer add class when property is true

I have seen this in angular before and wondered if this is possible in polymer as well. Angular - What is the best way to conditionally apply a class?
I have set up a property named 'animated':
animated: {
type: Boolean,
value: false,
},
When animated is true, a div inside my element should have a css class of .animate.
<div class=""></div>
For now I have done that inside of the ready function.
But since I came across that Stackoverflow question I wondered if this is prossible in polymer.
Thanks!
One way to do that is using a function as follow:
<div class$="{{_getClass(animated)}}"></div>
Where class$ with $ symbol indicates to Polymer's that property is generate using data binding. So, your _getClass function will look like this:
_getClass: function(animated){
return animated ? "animate" : "";
}
When animate property changes, the _getClass function will be invoked and this function will return the string that indicates the class you need.
You can also use toggleClass method of Polymer
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<dom-module id="my-element">
<template>
<style>
.show {
display: block !important;
border: 1px solid black;
}
.hide {
width: 100px;
height: 100px;
display: none;
}
</style>
<div class="hide" id="toggle"></div>
<button on-tap="_toggleDiv">Press to toggle</button>
</template>
</dom-module>
<script>
Polymer({
is: 'my-element',
properties: {
show: {
type: Boolean,
value: false
}
},
_toggleDiv: function() {
this.show = !this.show;
this.toggleClass('show', this.show, this.$.toggle);
}
});
</script>
<my-element></my-element>

Getting element by ID in coffeescript

I'm trying to create a HTML widget:
HTML:
<div>
<h1 class="title" data-bind="title">Title</h1>
<div>
<h1 id = "dc1" class="dc">DC1</h1>
</div>
<div>
<h1 id = "dc2" class="dc">DC2</h1>
</div>
<p class="updated-at" data-bind="updatedAtMessage"></p>
</div>
And I need to be able to set the background color of the id="dc1" and id="dc2" elements dynamically in CoffeeScript. I plan to do this by adding a class with a background color setting:
SCSS:
&.up {
background-color: green;
}
&.down {
background-color: red;
}
.dc {
background-color: orange;
font-size: 30px;
float: left;
width: 50%;
}
So far I have managed to set the whole widget background but not the child elements mentioned above:
I have been using:
CoffeeScript:
$(#node).removeClass('up down')
$('#dc1').removeClass('up down')
$('#dc2').removeClass('up down')
$(#node).addClass('down')
$('#dc1').addClass('down')
$('#dc2').addClass('up')
Note ultimately I will add the classes depending on some data rather than hard coding them to 'up' or 'down' in the coffeescript.
But nothing happends.. Am I getting selecting the id="dc#" elements correctly?
If it helps with context I'm doing this for Dashing
Your SCSS doesn't make sense so I'd guess that your missing an error from the SCSS-to-CSS conversion. An & in SCSS is a reference to the parent selector:
& will be replaced with the parent selector as it appears in the CSS
so have &.up at the top level makes no sense and should generate an error. If we fix the SCSS so that .up and .down apply only to .dc:
.dc {
/* ... */
&.up {
background-color: green;
}
&.down {
background-color: red;
}
}
then everything seems to work just fine.
Demo: http://jsfiddle.net/ambiguous/9y9uywm9/
You can use Sassmeister (and other similar online tools) to see what SCSS thinks of your original SCSS.

Polymer - styling childnodes of host

first, i searched for similar questions but haven't found a solution for my problem, which is basically simple, i guess. :)
I built a simple image-slider for clearing up the whole concepts of web components for myself with a real world example.
My custom component is made out of 5 components and a headline.
stage-slider
stage-element
h1
stage-button
stage-teaserdock
stage-teaser
The component slides fine. Now i wanted to add teaser navigation at the bottom. So first i tried adding a single teaser item.
Ok.. what i want to do is access an element inside of the stage-slider:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../stage-element/stage-element.html">
<link rel="import" href="../stage-button/stage-button.html">
<polymer-element name="stage-slider" attributes="items slideInterval">
<template>
<style>
:host {
width: 960px;
height: 485px;
position: absolute;
top: 50%;
left: 50%;
margin: -242px 0px 0px -480px;
overflow: hidden;
display: block;
}
:content .teaser
{
left: 30px;
}
</style>
<div id="wrapper">
<template id="slider" repeat="{{item in items}}">
<stage-element headline="{{item.headline}}"
image="{{item.image}}"
buttonLabel="{{item.buttonLabel}}"
buttonTargetWindow="{{item.buttonTargetWindow}}"
buttonTargetURL="{{item.buttonTargetURL}}">
</stage-element>
</template>
<content class="teaser" select="stage-teaser"></content>
</div>
</template>
<script src="./libs/TweenLite/easing/EasePack.min.js"></script>
<script src="./libs/TweenLite/plugins/CSSPlugin.min.js"></script>
<script src="./libs/TweenLite/TweenLite.min.js"></script>
</polymer-element>
<script>
Polymer('stage-slider',
{
slideInterval: 7000,
items: [],
index: 0,
ready: function ()
{
console.log('-----------------');
console.log('stage slider ready!');
},
attached: function ()
{
console.log('-----------------');
console.log('stage slider attached!');
this.$.wrapper.style.width = (960 * (this.items.length)).toString() + "px";
//
if (this.items.length > 1 && this.slideInterval != 0)
{
var that = this;
setInterval(function ()
{
that.startSliding(that);
}, this.slideInterval
);
}
},
startSliding: function (shadowDom)
{
console.log('More children than 1 -> SLIDE EM!');
TweenLite.to(shadowDom.$.wrapper, 1.5, {
marginLeft: -960,
ease: Expo.easeInOut,
onStart: function ()
{
console.log('tween started'); //, this = ', this);
},
onComplete: function ()
{
// console.log('tween complete');
// console.log(shadowDom.$.wrapper.getElementsByTagName('stage-slide')[0]);
shadowDom.$.wrapper.style.marginLeft = 0;
shadowDom.$.wrapper.appendChild(shadowDom.$.wrapper.getElementsByTagName('stage-element')[0]);
}});
}
});
</script>
This is how my markup looks like:
<stage-slider slideInterval="0"
items='[
{
"headline" : "Test headline",
"image" : "img/slide0.jpg",
"buttonLabel" : "Test buttonlabel",
"buttonTargetURL" : "http://www.google.com"
}
]'>
<stage-teaser class="teaser"
image="img/teaser0.jpg"
headline="Test teasertext"
targetURL="http://google.com">
</stage-teaser>
</stage-slider>
So there is a stage-teaser element nested inside my stage-slider element.
I thought i have to distribute it to the content tag inside my template element. Which is why there is a content tag like this:
<content class="teaser" select="stage-teaser"></content>
It displays the teaser item correctly.
But now i want to define its css from within the slider component. This is where i am totally stuck..
I can access the element itself with :host, thats good.
But how do i access the content element, which renders the teaser?
i tried the following:
:host(stage-teaser),
:host(.teaser),
:host(#teaser),
:content .teaser,
:host(:content .teaser),
as you can see.. i am kinda stuck. :-/
any idea would be cool!
thanks,
Rob
I suspect that the issue you're seeing is just a typo. Instead of :content you want ::content. Here's a jsbin showing a simple example: http://jsbin.com/mijifiru/1/edit and for more info on styling web components with the shadow DOM, check out this article: http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/
If that doesn't solve the issue it would be helpful if you reduced your code down to a Minimal, Complete, and Verifiable example, and for bonus points do so in an online editor like jsbin.
<polymer-element name='my-container' noscript>
<template>
<style>
::content .innerContent {
background-color: red;
}
</style>
Shadow Dom
<content></content>
</template>
</polymer-element>
<my-container>
<div class='innerContent'>Contained matching Light DOM</div>
<div>Contained unmatched Light DOM</div>
</my-container>