Polymer this.$ undefined in filter - polymer

I have a function called formatDate. This functions uses this.$ to access a global function in a global element. The only problem is that I am getting an error that says this.$ is undefined. I am not sure why that would ever be undefined. It is defined in the ready callback.
EDIT: Added code example. My problem is seen below in the formatDate function. this.$ is undefined.
<link rel="import" href="app-globals.html">
<polymer-element name="message-element" attributes="message">
<template>
<style>
:host {
display: block;
}
.message {
padding: 10px;
display: inline-block;
margin-bottom: 6px;
margin-right: 6px;
margin-left: 6px;
color: white;
clear: both;
max-width: 700px;
}
.sent-message {
background-color: #3F51B5;
float: right;
}
.received-message {
background-color: #C5CAE9;
float: left;
}
.sent-time {
font-size: 70%;
opacity: .54;
}
.clear {
clear: both;
display: block;
}
</style>
<div class="message {{message.type}}-message">
<app-globals id="globals"></app-globals>
<div>
{{message.message}}
</div>
<div class="sent-time">
{{message.sentDateTime | formatDate}}
</div>
</div>
</template>
<script>
Polymer({
formatDate: function(dateStr)
{
//console.log(this.$);
if(this.$ != null)
{
return this.$.globals.formatDate(dateStr);
}
}
});
</script>
</polymer-element>

Related

How to pass an image with props in vuejs without all the content disappearing when there's no image?

I have a component that in some cases will receive an image and in others it won't. So, I want this component to work in both ways. But, when it doesn't have any image, the other contents of this component, including styles doesn't work, they disappear. Is there a way that I can do this?
App.Vue:
<template>
<div id="app" class="raleway">
<link href='https://fonts.googleapis.com/css?family=Raleway' rel='stylesheet'>
<section class="title">
<Title name='Title' filename="twitter"/>
</section>
</div>
</template>
<script>
import Title from "./components/Title.vue";
export default {
name: "App",
components: {
Title,
},
};
</script>
<style>
html,
body {
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: #3B3B3B;
font-family: 'Raleway';
}
.title{
margin-top: 8em;
}
</style>
Component:
<template>
<div class="background">
<div class="title">
<h2><img :src="require(`#/assets/${filename}.svg`)" class="img">{{name}}</h2>
</div>
</div>
</template>
<script>
export default {
name: 'Background',
props:{
name: String,
filename: String,
}
}
</script>
<style scoped>
*{
margin: 0;
padding: 0;
}
.background{
background-color: #3B3B3B;
}
.title{
border: 1px solid #707070;
border-left: none;
border-right: none;
}
.title h2{
text-align: left;
color: #B16DFF;
padding-top: 0.5em;
font-size: 2em;
padding-bottom: 0.5em;
margin-left: 1.5em;
font-weight: 600;
}
.img{
padding-right: 1em;
}
#media(max-width: 580px){
.title h2{
font-size: 1.17em;
}
}
</style>
You could use v-if to conditionally render the <img> based on whether filename is truthy:
<img v-if="filename" :src="require(`#/assets/${filename}.svg`)">
I would pass in the image reference as a computed property, not requiring it directly in the source.
Then in the template you could use v-if to check if that was present, and render a 'no image' message using v-else if no image data present

Vue- How to change style of a same element in different components

I am trying to change the style of a specific div from one component to another. Each component is appended to the template in the App component and replaces the <router-view></router-view> tags. The div #app needs to have a padding of 172px in the Hello.vue component, and 0px on the rest of the components.Is this possible, and how can I accomplish this?
App.vue
<template>
<div id="app">
<div>
<img src="./assets/logo.png" align="center">
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
background-color: hsla(275, 97%, 50%, 0.57);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 0px;
height: inherit;
}
body{
height: inherit;
}
html{
height: 100%;
}
</style>
Hello.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<ul>
<li><h2><router-link to="/app/login">Login</router-link></h2></li>
<li><h2><router-link to="/app/about">About Us</router-link></h2></li>
</ul>
</div>
</template>
<script>
export default {
name: 'hello',
data () {
return {
msg: 'Welcome to Vue'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#app{
padding-top: 172px; /*This does not work*/
}
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #000000;
}
</style>
There is a quick way to do this (not sure if it's best practice) by checking the route path; assume Hello.vue is rendered via the path /hello:
<div id="app" :style="{ padding: $route.path === '/hello' ? '172px' : '0px' }">
...
</div>

CSS Variable trough Polymer (dynamically loaded) elements

I have multiple custom elements in my projects and I have a problem with css variables. In my parent element I have multiple item element with status classes. I want to manipulate the background and border color using that status classes, but I want to define the values in my parent element but somehow it not want to work.
Here my parent element:
<link rel="import" href="app-task.html" />
<dom-module id="app-task-grid">
<template>
<style>
:host {
display: block; position: absolute; left: 0; top: 0; width: 100%; height: 100%;
overflow:hidden; background: #eee;
--column-1-width: 80px;
--column-3-width: 120px;
--column-4-width: 180px;
--column-5-width: 220px;
--column-6-width: 100px;
--task-background-color: #eee;
--task-border-color: #ccc;
}
:host table.header {
position: absolute; top: 0; left: 0; width: 100%; height: 40px; background: #DDD;
}
:host table.header th {
letter-spacing: 2px; font-weight: normal; text-transform: uppercase;
font-size: 80%; border-left: 1px solid #aaa;
margin: 0; padding: 0 10px;
}
:host th.column1 {
width: var(--column-1-width);
}
:host th.column2 {
text-align: left;
}
:host th.column3 {
width: var(--column-3-width);
}
:host th.column4 {
width: var(--column-4-width);
}
:host th.column5 {
width: var(--column-5-width);
}
:host th.column6 {
width: var(--column-6-width);
text-align: left;
}
:host th.hide, :host td.hide {
display: none;
}
:host th.show, :host td.show {
display: table-cell;
}
:host table.header .scrollbar {
width: 20px; border-left: none;
padding: 0;
}
:host .items {
position: absolute; left: 0; top: 40px; right: 0; bottom: 0;
overflow:hidden; overflow-y: scroll;
margin: 0; padding: 0;
}
:host .items::-webkit-scrollbar {
width:22px; border-left: 6px solid #ddd;
background-color:#ddd;
}
:host .items::-webkit-scrollbar-thumb {
background-color:#aaa;
border-left: 6px solid #ddd;
min-height: 80px;
}
.waiting {
--task-background-color: #e9d32c;
--task-border-color: #b0a030;
}
.assigned {
--task-background-color: #1b7eee;
--task-border-color: #1357a4;
}
.started {
--task-background-color: #EF6207;
--task-border-color: #c05d1d;
}
.working {
--task-background-color: #e99c2c;
--task-border-color: #c48222;
}
.aborted {
--task-background-color: #E34126;
--task-border-color: #b72d15;
}
</style>
<table class="header">
<tr>
<th class="column1"></th>
<th class="column2">Column#2</th>
<th class="column3">Column#3</th>
<th class="column4">Column#4</th>
<th class="column5">Column#5</th>
<th class="column6">Column#6</th>
<th class="scrollbar"></th>
</tr>
</table>
<div class="items">
<app-task id="task0" class="waiting"></app-task>
</div>
</template>
<script>
Polymer({
is:"app-task-grid",
loadItems: function()
{
let statuses = ['waiting','assigned','started','working','aborted'];
for(var i = 1; i<=30; i++)
{
let itemStatus = statuses[Math.floor(Math.random()*statuses.length)];
let itemElement = document.createElement('APP-TASK');
itemElement.id = 'task'+i;
itemElement.classList.add(itemStatus);
console.debug( itemElement );
this.querySelector('.items').appendChild( itemElement );
}
}
});
</script>
</dom-module>
My children element:
<dom-module id="app-task">
<template>
<style>
:host {
display: block; margin: 8px 0; padding: 0;
}
:host table {
width: 100%; height: 80px;
background-color: var(--task-background-color, #fff);
border-bottom: 5px solid var(--task-background-color, #fff);
border-top: 5px solid var(--task-background-color, #fff);
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.07),
0 1px 5px 0 rgba(0, 0, 0, 0.06),
0 3px 1px -2px rgba(0, 0, 0, 0.1);
}
:host table td {
border-left: 1px solid var(--task-border-color, #ccc);
margin: 0; padding: 0 10px;
}
:host td.column1 {
width: var(--column-1-width);
}
:host td.column2 {
}
:host td.column3 {
width: var(--column-3-width);
}
:host td.column4 {
width: var(--column-4-width);
}
:host td.column5 {
width: var(--column-5-width);
}
:host td.column6 {
width: var(--column-6-width);
}
</style>
<table>
<tr>
<td class="column1">C#1</td>
<td class="column2">C#2</td>
<td class="column3">C#3</td>
<td class="column4">C#4</td>
<td class="column5">C#5</td>
<td class="column6">C#6</td>
</tr>
</table>
</template>
<script>
Polymer({
is:"app-task"
});
</script>
</dom-module>
I tried already:
:host .waiting { ... }
:host app-task.waiting { ... }
app-task.waiting { ... }
:root .waiting { ... }
:root app-task.waiting { ... }
:root { .waiting { ... } }
:root { app-task.waiting { ... } }
parent element for the app-task for the classes
style is="custom-style" inside the app-grid template
style is="custom-style" outside the template but inside the app-grid element html file
but none of them seems working.
If I define the css variables in the :host then it's working, only not working with classes somehow. Where did made a mistake?
UPDATE#1:
Something weird hapening with the style-scope, if I add the "style-scope app-task-grid" to the parent element for the tasks:
<div class="items">
<div class="style-scope app-task-grid waiting">
<app-task id="task1"></app-task>
</div>
</div>
then if I add a normal css rule like a color its applied in the app-task, but the css variables are not.
UPDATE#2:
As it was mention that this template is working, and I tested it and it is, !But id did not mention that the items are created on the fly and appended to the items. I added almost everything from my code on Plunker: http://plnkr.co/edit/b5XW1w3sEOy4UHc0rdWH?p=preview
Sorry about my mislead, I did not know that the problem source was the dynamic load.
Note: I updated the question with more example.
UPDATE#3:
Thanks to #a1626s and #GünterZöchbauer we found the answer:
My initial code was good and worked from the beginning, I defined the questions badly becasue I did not see what was the problem. So if somebody dynamically load elements inside an element must use Polymer.dom api.
Polymer.dom(this.querySelector('.items')).appendCild(itemElement);
I don't see any problem in your initial code. I copied your code and pasted it in plunker
<style>
:host {
display: block;
}
.waiting {
--task-background-color: #e9d32c;
--task-border-color: #b0a030;
}
.assigned {
--task-background-color: #1b7eee;
--task-border-color: #1357a4;
}
.started {
--task-background-color: #EF6207;
--task-border-color: #c05d1d;
}
.working {
--task-background-color: #e99c2c;
--task-border-color: #c48222;
}
.aborted {
--task-background-color: #E34126;
--task-border-color: #b72d15;
}
</style>
<div class="items">
<app-task id="task1" class="waiting"></app-task>
<app-task id="task2" class="waiting"></app-task>
<app-task id="task3" class="working"></app-task>
<app-task id="task4" class="working"></app-task>
<app-task id="task5" class="assigned"></app-task>
<app-task id="task6" class="aborted"></app-task>
</div>
and it seemed to be working fine for me.
As for your new problem replace your javascript method with this method and it should work.
{
let statuses = ['waiting','assigned','started','working','aborted'];
for(var i = 1; i<=30; i++)
{
let itemStatus = statuses[Math.floor(Math.random()*statuses.length)];
let itemElement = document.createElement('APP-TASK');
itemElement.id = 'task'+i;
itemElement.classList.add(itemStatus);
console.debug( itemElement );
Polymer.dom(this.$.items).appendChild(itemElement);
}
Polymer.dom.flush();
}
Also, here is the change that i made in your app-task-grid element
<div class="items" id="items"> //added id attribute to the div tag
The problem being the way you are adding child elements they do not get properly inserted into dom tree of the element. Polymer has documentation on how to work with tree of its elements. You can read more about it here
Remember that the <style> where the CSS variables are set must have is="custom-style" in the tag.
I've thrown together a very crude snippet to show it.
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<dom-module id="app-task">
<template>
<style>
:host {
display: block;
height: 80px;
margin: 5px;
background-color: var(--task-background-color, #fff);
border: 1px solid var(--task-border-color, #ccc);
}
</style>
<div>some stuff...</div>
</template>
<script>
Polymer({
is: 'app-task'
});
</script>
</dom-module>
<!-- Beginning of the 'parent element' -->
<style is="custom-style">
.waiting {
--task-background-color: #e9d32c;
--task-border-color: #b0a030;
}
.assigned {
--task-background-color: #1b7eee;
--task-border-color: #1357a4;
}
.started {
--task-background-color: #EF6207;
--task-border-color: #c05d1d;
}
.working {
--task-background-color: #e99c2c;
--task-border-color: #c48222;
}
.aborted {
--task-background-color: #E34126;
--task-border-color: #b72d15;
}
</style>
<div class="items">
<app-task id="task1" class="waiting"></app-task>
<app-task id="task2" class="waiting"></app-task>
<app-task id="task3" class="working"></app-task>
<app-task id="task4" class="working"></app-task>
<app-task id="task5" class="assigned"></app-task>
<app-task id="task6" class="aborted"></app-task>
</div>
Another example with it running through several elements
<script src="https://polygit.org/components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="https://polygit.org/components/polymer/polymer.html">
<dom-module id="app-task">
<template>
<style>
:host {
display: block;
height: 80px;
margin: 5px;
background-color: var(--task-background-color, #fff);
border: 1px solid var(--task-border-color, #ccc);
}
</style>
<div>some stuff...</div>
</template>
<script>
Polymer({
is: 'app-task'
});
</script>
</dom-module>
<!-- Beginning of the 'parent element' -->
<dom-module id="app-task-grid">
<template>
<!-- normal styles -->
<style>
app-task {
width: 50%;
margin: 10px auto;
}
</style>
<!-- custom styles -->
<style is="custom-style">
.waiting {
--task-background-color: #e9d32c;
--task-border-color: #b0a030;
}
.assigned {
--task-background-color: #1b7eee;
--task-border-color: #1357a4;
}
.started {
--task-background-color: #EF6207;
--task-border-color: #c05d1d;
}
.working {
--task-background-color: #e99c2c;
--task-border-color: #c48222;
}
.aborted {
--task-background-color: #E34126;
--task-border-color: #b72d15;
}
</style>
<div class="items">
<app-task id="task1" class="waiting"></app-task>
<app-task id="task2" class="waiting"></app-task>
<app-task id="task3" class="working"></app-task>
<app-task id="task4" class="working"></app-task>
<app-task id="task5" class="assigned"></app-task>
<app-task id="task6" class="aborted"></app-task>
</div>
</template>
<script>
Polymer({
is: 'app-task-grid'
});
</script>
</dom-module>
<!-- And now pushing it to the screen -->
<app-task-grid></app-task-grid>

Reference element in shadow root

Say I had this code: (or visit this codepen link)
<script src="https://www.polymer-project.org/webcomponents.js"></script>
<link rel="import" href="https://www.polymer-project.org/components/core-scaffold/core-scaffold.html">
<style>
body {
font-family: sans-serif;
}
core-scaffold {
}
core-header-panel {
float: left;
height: 400px;
}
.core-header {
height: 64px;
line-height: 60px;
font-size: 18px;
padding: 0 10px;
background-color: #FF66CC;
color: #FFF;
transition: height 0.2s;
}
.core-header-content {
padding: 20px;
}
.main-menu {
background: transparent;
}
.search {
position: static;
border: 0;
padding: 0;
display: inline-block;
}
.search core-icon {
display: inline-block;
}
.search input {
box-sizing: border-box;
-moz-box-sizing: border-box;
position: static;
display: inline-block;
}
</style>
<core-scaffold responsiveWidth="9999px">
<core-header-panel mode="seamed" navigation flex>
<core-toolbar>
<span flex>Title</span>
<core-icon-button icon="refresh"></core-icon-button>
<core-icon-button icon="add"></core-icon-button>
</core-toolbar>
<core-menu>
<core-item label="One"></core-item>
<core-item label="Two"></core-item>
</core-menu>
</core-header-panel>
<core-toolbar class="main-menu" tool flex>
<span flex>Title</span>
<core-icon-button icon="settings" on-tap="{{settingsAction}}"></core-icon-button>
</core-toolbar>
<div class="core-header-content">
</div>
</core-scaffold>
How would I go about referencing the #menuButton core-icon-button (which is automatically generated by the core-scaffold) to change the attribute value of 'icon' from 'menu' to 'apps'?
It's probably something simple I've overlooked and thanks in advance.
Found the answer:
document.addEventListener('polymer-ready', function(e) {
$('core-scaffold::shadow #drawerPanel #headerPanel core-toolbar #menuButton').attr('icon','apps');
});

Polymer element's on-keypress won't fire

I bind a on-keypress event on my element with Declarative event mapping, but the keypressHandler wont fire. I did try the answer from another question, still the same. Here is my DOME, my element is gdg-slider.html, and all the codes are on github.
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/core-icons/core-icons.html">
<link href="bower_components/core-animated-pages/core-animated-pages.html" rel="import">
<link href="bower_components/core-animated-pages/transitions/cross-fade.html" rel="import">
<link href="bower_components/core-animated-pages/transitions/slide-from-right.html" rel="import">
<link rel="import" href="bower_components/paper-shadow/paper-shadow.html">
<link rel="import" href="bower_components/paper-fab/paper-fab.html">
<polymer-element name="gdg-slider" on-keypress="{{keypressHandler}}">
<template>
<style>
core-animated-pages{
position: absolute;
top: 0px;
right: 0;
bottom: 0;
left: 0;
font-size: 32px;
overflow: hidden;
background-color: #222;
color: #eee;
}
p,h1,h2,h3,h4,h5{
padding: 5px;
margin: 0;
word-break: break-all;
}
h1{
padding: 10px;
}
section{
width: 100%;
}
section > div {
height: 100%;
padding: 0 30px;
}
section.nav{
position: absolute;
bottom: 30px;
left: 0;
}
section.nav>div{
padding: 0 30px;
}
section.nav>div:first-child{
padding-right: 0;
}
#preBtn{
background: #999;
}
.me{
border-radius: 500px;
}
code{
color: #9f499b;
padding: 0 5px;
}
div{
padding: 5px;
}
a,a:active,a:visited,a:link{
padding: 0 5px;
color: #e7ad52 !important;
text-decoration: none;
}
a:hover{
text-decoration: underline;
}
.right{
position: absolute;
top: -90px;
left: -90px;
width: 170px;
height: 170px;
-webkit-transform: rotate(-45deg);
font-size: 14px;
background: #999;
font-weight: bold;
color: #fff;
}
</style>
<core-animated-pages id="pages" transitions="slide-from-right" selected="{{pageIndex}}">
<section style="overflow: hidden;">
<p class="right" layout vertical center end-justified><span>Powered by Polymer</span><paper-shadow z="5"></paper-shadow></p>
<div layout vertical center center-justified>
<img src="resources/images/p-logo.svg"/>
<h1>Polymer</h1>
<p>Welcome To The World Of Tomorrow!</p>
</div>
</section>
<section>
<div layout vertical center-justified>
</div>
</section>
//more sections...
</core-animated-pages>
<section class="nav" layout horizontal end-justified>
<div layout horizontal><paper-fab start-justified icon="icons:arrow-back" id="preBtn" on-click="{{prePage}}"><paper-shadow z="5"></paper-shadow></paper-fab></div>
<div layout horizontal><paper-fab icon="icons:arrow-forward" id="nextBtn" on-click="{{nextPage}}"><paper-shadow z="5"></paper-shadow></paper-fab></div>
</section>
</template>
<script>
Polymer('gdg-slider',{
pageIndex: 0,
pageMax: 0,
ready: function(){
this.pageMax = this.$.pages.children.length-1;
this.$.pages.focus();
this.pageIndex = parseInt(window.location.hash.replace('#','') || 0);
this.toggleBtns();
},
keypressHandler: function(event, detail, sender){
var code = event.keyCode;
if(code==32 || code==39){
this.nextPage();
}else if(code==37){
this.prePage();
}
},
prePage: function(){
this.pageIndex -= 1;
if(this.pageIndex <= 0) {
this.pageIndex = 0;
}
window.location.hash = this.pageIndex;
this.toggleBtns();
},
nextPage: function() {
this.pageIndex += 1;
if(this.pageIndex >= this.pageMax) {
this.pageIndex = this.pageMax;
}
window.location.hash = this.pageIndex;
this.toggleBtns();
},
toggleBtns: function(){
if(this.pageIndex >= this.pageMax) {
this.$.nextBtn.hidden = true;
}else{
this.$.nextBtn.removeAttribute('hidden');
}
if(this.pageIndex <= 0) {
this.$.preBtn.hidden = true;
}else{
this.$.preBtn.removeAttribute('hidden');
}
}
});
</script>
</polymer-element>
You're calling this.$.pages.focus(), but you haven't given #pages a tabindex, so it's not focusable. That's why your keypress events aren't firing.
Add tabindex="0" to #pages to fix it.
Here's a working jsbin.