Polymer: Bind custom-element's data to main document - polymer

I have create a custom element to show chat list as follows:
<dom-module id="contact-element">
<style>
--paper-card: {
width: 100%;
}
.edit{
display: block;
}
.last{
color: #A7A7A7;
font-size: 14px;
margin-top: 4px;
}
</style>
<template>
<template is="dom-repeat" items="{{contacts}}">
<div>
<paper-card class="contactcard" on-click="setUser">
<div class="card-content">
<div>{{ item.name }}</div>
<div class="last">{{ item.last }}</div>
</div>
</paper-card>
</div>
</template>
</template>
<script>
HTMLImports.whenReady(function () {
Polymer({
is: 'contact-element',
properties: {
user: {
type: Object,
},
username: {
type: String,
reflectToAttribute: true,
}
},
ready: function(){
this.contacts = [
{name: "Rajat",last: "How are you!", unread: 1},
{name: "Neeraj",last: "Okay", unread: 0},
{name: "Vaibhav"},
{name: "Rohit"},
{name: "Hitesh"},
];
},
setUser: function(e){
var model = e.model;
this.user = model.get('item');
this.username = this.user.name;
console.log("user set: "+model.get('item.name'));
}
});
});
</script>
</dom-module>
And I want that when a user clicks on any of the object, the toolbar should get the name. For that I'm using:
<paper-toolbar>
<paper-icon-button icon="menu" paper-drawer-toggle paper-drawer-left></paper-icon-button>
<span class="flex"></span>
<!-- Title -->
<div class="app-name flex">[[ pagetitle ]]</div>
<paper-icon-button icon="add-alert"></paper-icon-button>
<paper-icon-button icon="question-answer" paper-drawer-toggle paper-drawer-right></paper-icon-button>
</paper-toolbar>
But it's not working. Any help?

I solve this by putting notify='true' into the script tag like this:
properties: {
user: {
type: Object,
notify: true
},
username: {
type: String,
reflectToAttribute: true,
}
},
Notify lets the data change event bounce up, to the element housing our custom element.

Related

Variable isn't being accessed by inline style Vue 3

I'm trying to pass a prop to my inline :style in Vue 3, but for some reason I'm unable to do it. Here's my code. Any help is appreciated.
<template>
<div style="width: 100vw;" :style="{'min-height': props.rem}"></div>
</template>
const props = defineProps({
rem: Number
})
Try to add 'rem' to min-height style prop:
const app = Vue.createApp({
data() {
return {
nr: 10,
};
},
})
app.component('child', {
template: `
<div class="child" style="width: 100vw;" :style="{'min-height': rem+'rem'}"> rem = {{ rem }}</div>
`,
props: {
'rem': {
type: Number,
default: 5
}
},
})
app.mount('#demo')
.child {
background-color: purple;
}
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<child :rem="nr"></child>
</div>

How can I use v-html to pass a text with props and images?

I'm trying to pass different texts to a component list. Each text has a different title and also different content, but the same style. To do this I'm using another component that takes a v-html. I need to pass an image inside this v-html and also several props. However, the image does not appear and the props do not work. How can I solve this? I don't want to change my "message" component because I'm using it in other areas of my website and it's working fine.
App.Vue:
<template>
<div id="app" class="raleway">
<link href='https://fonts.googleapis.com/css?family=Raleway' rel='stylesheet'>
<section class="container grid">
<div
v-for="metadata in this.metadatas"
:key="metadata.id"
class="steps-wrapper text"
>
<Team :metadata="metadata"/>
</div>
</section>
</div>
</template>
<script>
import Team from "./components/Team.vue";
export default {
name: "App",
components: {
Team,
},
data() {
return {
metadatas: [
{
id: 1,
name: "Title1",
country: "Brazil"
},
{
id: 2,
name: "Title2",
country: "England"
},
],
};
},
};
</script>
Component (Team):
<template>
<div id="app" class="raleway">
<section>
<div class="steps-wrapper text">
<Step/>
<div class="image-cropper">
<img src="../assets/me.jpg" alt="" class="profile-pic">
</div>
<Message v-html="content" />
</div>
</section>
</div>
</template>
<script>
import Step from "./CreationView";
import Message from "./Message";
export default {
name: "App",
components: {
Step,
Message
},
props: {
metadata: Object,
},
data() {
return {
content:
"<h2>{{metadata.name}}</h2>\
<h2><img src='../assets/discord.svg' alt=''>Head</h2>\
<p id='country'> {{metadata.country}} </p>\
};
},
};
</script>
Component (Message):
<template>
<div class="container">
<section>
</section>
</div>
</template>
<script>
export default {
name: 'Message',
}
</script>

PassingData using app route in polymer

I would like to pass the id of the selected grid using app-router. Somehow I seem to be missing a link. I want to be able to pass the id of the selected row from the grid and use that value in the iron-ajax url http://192.168.178.31:8080/demo/questions?assessmentId=TEST in place if assessmentId.
my-data.html
<dom-module id="my-data">
<template>
<style include="shared-styles">
:host {
display: block;
padding: 10px;
}
.title {
margin-left: 40%;
}
.card {
height: 100%;
}
</style>
<div class="card">
<div class="title">ASSESSMENTS</div>
<!-- Fetch an array of users to be shown in the grid -->
<vaadin-grid id="material" items="{{assessments}}" selected-items={{selectedItems}} active-item="{{selectedItem}}">
<vaadin-grid-selection-column auto-select frozen>
</vaadin-grid-selection-column>
<vaadin-grid-column>
<template class="header">Assessment Id</template>
<template>[[item.assessmentId]]</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">Assessment Topic</template>
<template>[[item.assessmentTopic]]</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">Assessment Subtopic</template>
<template>[[item.assessmentSubtopic]]</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">Created By</template>
<template>[[item.createdBy]]</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">Rating</template>
<template>[[item.rating]]</template>
</vaadin-grid-column>
</vaadin-grid>
<app-location route="{{route}}" url-space-regex="^[[rootPath]]">
</app-location>
<app-route route="{{route}}"
pattern="[[rootPath]]:page"
data="{{routeData}}"
tail="{{subroute}}">
</app-route>
<iron-selector selected="[[page]]" attr-for-selected="name" class="drawer-list" role="navigation">
<a name="assessment" href="[[rootPath]]assessment">Quiz Page</a>
</iron-selector>
</div>
</template>
<script>
class MyData extends Polymer.Element {
static get is() { return 'my-data'; }
static get properties() {
return {
index: {
type: Number,
value: 0
},
assessments: {
type: Array,
observer: 'isAssessmentLoaded'
},
selectedItem: {
type: Array,
},
selectedItems: {
type: Array,
},
page: {
type: String,
reflectToAttribute: true,
observer: '_pageChanged',
},
routeData: Object,
subroute: String,
// This shouldn't be neccessary, but the Analyzer isn't picking up
// Polymer.Element#rootPath
rootPath: String,
};
}
constructor() {
super();
}
_selectedItemsChanged(selectedItem, selectedItems) {
console.log(selectedItems);
this.selectedItem = selectedItem;
}
isAssessmentLoaded(q) {
if (q) {
console.log('loaded questions', q); // questions are loaded.
}
}
redirect() {
page('/')
}
static get observers() {
return [
//'_routePageChanged(routeData.page)',
'_selectedItemsChanged(selectedItem, selectedItems)'
];
}
// _routePageChanged(page) {
// // If no page was found in the route data, page will be an empty string.
// // Default to 'assessments' in that case.
// this.page = page | 'assessment';
// // Close a non-persistent drawer when the page & route are changed.
// // if (!this.$.drawer.persistent) {
// // this.$.drawer.close();
// // }
// }
// _pageChanged(page) {
// // Load page import on demand. Show 404 page if fails
// var resolvedPageUrl = this.resolveUrl('my-' + page + '.html');
// Polymer.importHref(
// resolvedPageUrl,
// null,
// this._showPage404.bind(this),
// true);
// }
_showPage404() {
this.page = 'view404';
}
}
window.customElements.define(MyData.is, MyData);
</script>
</dom-module>
my-assessment.html
<dom-module id="my-assessment">
<template>
<style include="shared-styles">
:host {
display: block;
padding: 10px;
}
</style>
<!--Check the url is correct ! And last responce property should be {{}} instead [[]] (as up way data binding) -->
<iron-ajax
id="requestRepos"
url="http://192.168.178.31:8080/demo/questions?assessmentId=TEST"
handle-as="json"
last-response="{{repos}}">
</iron-ajax>
<template is="dom-if" if="{{repos}}">
<my-quiz repos= "{{repos}}"></my-quiz>
</template>
</template>
<script>
class Assessment extends Polymer.Element {
static get is() { return 'my-assessment'; }
constructor() {
super();
}
ready() {
super.ready();
this.$.requestRepos.generateRequest();
}
}
window.customElements.define(Assessment.is, Assessment);
</script>
</dom-module>
Here is how to change the route by clicking on the link:
<app-location
route="{{route}}"
use-hash-as-path="">
</app-location>
<app-route
route="{{route}}"
pattern="/:page"
data="{{routeData}}"
tail="{{subroute}}">
</app-route>
<a name="some_name" href="#/some_route">Change route</a>

polymer 1.0 dom-repeat filter only runs once

When I change the year using the drop-down, I want the list to re-filter and display the info for that chosen year. What am I missing? Changing the year does not re-filter the dom-repeat.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<base href="http://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<title>dropdown</title>
<link rel="import" href="http://polygit.org/components/paper-menu/paper-menu.html">
<link rel="import" href="http://polygit.org/components/paper-item/paper-item.html">
<link rel="import" href="http://polygit.org/components/paper-button/paper-button.html">
<link rel="import" href="http://polygit.org/components/paper-menu-button/paper-menu-button.html">
<style>
.taller{
height:120px;
}
[vertical-align="top"] ul {
margin-top: 0;
}
[vertical-align="bottom"] ul {
margin-bottom: 0;
}
button, paper-button {
border: 1px solid #ccc;
background-color: #eee;
/*padding: 1em;*/
border-radius: 3px;
cursor: pointer;
}
button:focus {
outline: none;
border-color: blue;
}
</style>
</head>
<body>
<dom-module id="x-demo">
<template>
<div class="horizontal-section flex layout horizontal taller">
<paper-menu-button>
<paper-button icon="menu" class="dropdown-trigger"><span>Year<br/></span><span>{{year}}</span></paper-button>
<paper-menu id="selectedYear" class="dropdown-content" selected="{{selectedIndex}}">
<template is="dom-repeat" items="{{allData}}">
<paper-item on-tap='yearTapped'>{{item.year}}</paper-item>
</template>
</paper-menu>
</paper-menu-button>
<paper-menu-button>
<paper-button icon="menu" class="dropdown-trigger"><span>Make<br/></span><span>{{make}}</span></paper-button>
<paper-menu id="selectedMake" class="dropdown-content" selected="{{selectedIndex}}">
<template is="dom-repeat" items="{{allData}}">
<paper-item on-tap='makeTapped'>{{item.make}}</paper-item>
</template>
</paper-menu>
</paper-menu-button>
<paper-menu-button>
<paper-button icon="menu" class="dropdown-trigger"><span>Model<br/></span><span>{{model}}</span></paper-button>
<paper-menu id="selectedModel" class="dropdown-content" selected="{{selectedIndex}}">
<template is="dom-repeat" items="{{allData}}">
<paper-item on-tap='modelTapped'>{{item.model}}</paper-item>
</template>
</paper-menu>
</paper-menu-button>
<paper-menu-button>
<paper-button icon="menu" class="dropdown-trigger"><span>Engine<br/></span><span>{{engine}}</span></paper-button>
<paper-menu id="selectedEngine" class="dropdown-content" selected="{{selectedIndex}}">
<template is="dom-repeat" items="{{allData}}">
<paper-item on-tap='engineTapped'>{{item.engine}}</paper-item>
</template>
</paper-menu>
</paper-menu-button>
</div>
<div>Vehicle list filtered by selected year: </div>
<template is="dom-repeat" id="vehicleList" items="{{allData}}" filter="yearMatch" observe="year item.year">
<div>Year <span>{{item.year}}</span></div>
<div>Make <span>{{item.make}}</span></div>
<div>Model <span>{{item.model}}</span></div>
<div>Engine <span>{{item.engine}}</span></div>
<button on-click="toggleSelection">Select</button>
</template>
<array-selector id="selector" items="{{allData}}" selected="{{selected}}" multi toggle></array-selector>
<div>Selected vehicle: </div>
<template is="dom-repeat" items="{{selected}}">
<div><span>{{item.year}}</span></div>
<div><span>{{item.make}}</span></div>
<div><span>{{item.model}}</span></div>
<div><span>{{item.engine}}</span></div>
</template>
</template>
<script>
Polymer({
is: 'x-demo',
properties:{
allData:{type:Array,
value: function() {
return [{year:'2015',make:'HONDA',model:'CB300F',engine:'300cc'},
{year:'2014',make:'HONDA',model:'CBR300R',engine:'300cc'}];
}
},
year:{type:String,value:'2014',notify:true}
},
observers: [
'yearChanged(year)'
],
yearChanged: function(item) {
console.log(item);
this.set('item.year', item);
this.$.vehicleList.render();
},
yearMatch: function(item) {
console.log('year checked');
return item.year = this.year;
},
toggleSelection: function(e) {
var item = this.$.vehicleList.itemForElement(e.target);
this.$.selector.select(item);
},
yearTapped: function(e) {
this.year=e.target.innerText;
},
makeTapped: function(e) {
this.make=e.target.innerText;
},
modelTapped: function(e) {
this.model=e.target.innerText;
},
engineTapped: function(e) {
this.engine=e.target.innerText;
}
});
</script>
</dom-module>
<x-demo></x-demo>
</body>
</html>
this works for me
<script>
HTMLImports.whenReady(function () {
Polymer({
is: 'x-demo',
properties:{
allData:{
type:Array,
value: [{
year:'2015',
make:'HONDA',
model:'CB300F',
engine:'300cc'
}, {
year:'2014',
make:'HONDA',
model:'CBR300R',
engine:'300cc'
}]
},
year:{
type:
String,
value:'2014',
observer: 'yearChanged'
}
},
yearChanged: function() {
console.log(this.year)
this.$.vehicleList.render();
},
yearMatch: function(item) {
return item.year == this.year;
},
toggleSelection: function(e) {
var item = this.$.vehicleList.itemForElement(e.target);
this.$.selector.select(item);
},
yearTapped: function(event) {
var res = event.target.innerText || event.target.textContent;
this.year = res.replace(/\s+/g, '');
},
makeTapped: function(event) {
var res = event.target.innerText || event.target.textContent;
this.make = res.replace(/\s+/g, '');
},
modelTapped: function(event) {
var res = event.target.innerText || event.target.textContent;
this.model = res.replace(/\s+/g, '');
},
engineTapped: function(event) {
var res = event.target.innerText || event.target.textContent;
this.engine = res.replace(/\s+/g, '');
}
});
});

Can't get my input focus to work?

Why does my this.$.search.focus() not work?
<polymer-element name="site-search">
<template>
<style>
:host {
font-family: 'RobotoDraft', sans-serif;
font-size: 14px;
}
.condensed input, .condensed /deep/ .underline {
display: none;
}
</style>
<section horizontal layout>
<core-icon-button
id="button"
icon="search"
title="search"
aria-label="search"
disabled?="{{!canBeCondensed}}"
on-tap="{{toggleSearch}}">
</core-icon-button>
<paper-input-decorator flex
label="{{label}}"
floatingLabel="{{floatingLabel}}"
value="{{value}}"
disabled?="{{disabled || condensed}}"
class="{{ {condensed: condensed} | tokenList }}">
<input
id="search"
on-blur="{{onBlur}}"
type="search"
value="{{value}}"
committedValue="{{committedValue}}"
on-keyup="{{onKeyUp}}"
disabled?="{{disabled}}">
</paper-input-decorator>
</section>
</template>
<script>
Polymer({
publish: {
label: '',
floatingLabel: false,
disabled: {value: false, reflect: true},
canBeCondensed: false,
condensed: false,
site: window.location.hostname
},
toggleSearch: function() {
if (!this.canBeCondensed) return;
this.$.search.focus() <==== Doesn't work. Why?
this.condensed = !this.condensed;
this.$.button.hidden=true
},
onKeyUp: function(e) {
if (e.keyCode == 13) { // Enter.
var q = encodeURIComponent('site:' + this.site + ' ' + this.value);
window.open('https://www.google.com/search?q=' + q);
}
},
onBlur:function(e) {
this.condensed = !this.condensed;
this.$.button.hidden=false
},
});
</script>
</polymer-element>
Try removing .condensed input, in your css.
Because when you change the class of the paper-input-decorator, your original css will update the inner input's class too, and this will cause the input to lose focus.
Alternatively, you can remove the whole class="{{ {condensed: condensed} | tokenList }}" and hide/show the underline element in js. For example -
toggleSearch: function () {
if (!this.canBeCondensed) return;
this.$.search.focus();
//this.condensed = !this.condensed;
this.$.button.hidden = true;
var underline = document.querySelector('paper-input-decorator::shadow .underline');
underline.hidden = true;
},