Declaring events in polymer - javascript

I have the following element declared in polymer
<polymer-element name="Map-List-Element" attributes="mapName recordId">
<template>
<style>
:host {
display: block;
position: relative;
background-color:#fff;
padding: 20px;
font-family: 'Roboto';
font-size:14px;
font-weight:400;
margin-bottom:10px;
border: 1px solid #ddd;
}
core-label {
margin-bottom:20px;
display:block;
}
core-icon {
color:#A0A0A0;
margin-right:10px;
cursor:pointer;
}
</style>
<core-label>{{mapName}}</core-label>
<span flex></span>
<core-icon-button icon="av:play-arrow"></core-icon-button>
<core-icon icon="settings" on-tap="{{settingsClicked}}"></core-icon>
<core-icon icon="delete"></core-icon>
<content/>
</template>
<script>
Polymer({
mapName: "",
recordId: 0,
settingsClicked: function (event, detail, sender) {
this.fire('show-Settings', { recordId: this.recordId, mapName: this.name });
}
});
</script>
</polymer-element>
That in turn is called by the following custom element
<link rel="import" href="elements.html" />
<link rel="import" href="Map-List-Element.html" />
<polymer-element name="Map-List">
<template>
<template repeat="{{m in response.data}}">
<map-list-element mapname="{{m.mapName}}" recordid="{{m.Id}}" on-show-settings="{{showSettings}}">
</map-list-element>
</template>
<core-ajax id="ajax"
auto=true
method="POST"
url="/RoutingMapHandler.php?Command=retrieve&Id=all"
response="{{response}}"
handleas="json"
on-core-error="{{handleError}}"
on-core-response="{{handleResponse}}">
</core-ajax>
</template>
<script>
Polymer('Map-List', {
created: function () {
},
handleError: function (event, detail, sender) {
},
handleResponse: function (event,detail,sender) {
},
showSettings: function (event, detail, sender) {
alert('Fired showSettings');
}
});
</script>
</polymer-element>
When I click on the core-icon with the settings icon it calls the 'settingsClicked' function. The 'event handler' in the Map-List element which contains another alert is not called - the alert in 'showSettings' is not shown.
So given the events declared in the Map-Element element, how do you create the event handler in the Map-List?

Your event handler declaration is correct (on-show-settings="{{showSettings}}" and the corresponding function).
But you got a typo in the fire statement .The event name must be all lowercase. So replace this.fire('show-Settings' with this.fire('show-settings' and your code will work.

Related

pass emit click to parent in slot element to run function in parent vue 3 slot option api

greeting king,
I'm trying to emit click from child(todoitem.vue) element that contains button and slot in this component to parent(app.vue) that will run a method in parent. For example now when I click edit button then method in parent editable() will run and when I click delete button then run method of deletable() in parent. How to approach this. I had tried to pass using v-slot but it only send variable also try emit but failed to emit. I'm totally new to vue..thanks
parent(app.vue)
<template>
<div>
<todolist>
<todoitem v-for="each in a" :key="each.list">
{{each.list}}
</todoitem>
</todolist>
<todolist>
<todoitem v-for="each in b" :key="each.list">
{{each.list}}
</todoitem>
</todolist>
</div>
</template>
<script>
import todolist from "./components/todolist.vue";
import todoitem from "./components/todoitem.vue";
export default {
name: "App",
data(){
return{
a:[
{list:"AAAA"},
{list:"BBBB"},
{list:"CCC"},
],
b:[
{list:"DDDD"},
{list:"EEEE"},
{list:"FFFF"},
],
}
},
components: {
todolist,
todoitem
},
methods:{
editable(){
console.log('editabel')
},
deletable(){
console.log('deletable')
}
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
child(todoitem)
<template>
<slot></slot>
<button #click="test">Edit</button>
<button #click="test2">delete</button>
</template>
<script>
export default {
name: "todoitem",
method:{
test(){
console.log('edit click')
this.$emit('edit-item')
},
test2(){
console.log('delete click')
this.$emit('del-item')
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
todolist
<template>
<slot></slot>
<div>
</div>
</template>
<script>
export default {
name: "todolist",
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
Basically it's structured like this - just put an emit with the function-name and the paramters inside of one of your methods like this:
Child.vue
this.$emit("Your_Function_Name", Parameter_1, Parameter_2);
Than go to your parent.vue call your emitted function and use it inside your methods of the parent.vue:
Parent.vue
<template>
...
<Child #Your_Function_Name="Your_Function_Name">
...
</template>
<script>
methods: {
Your_Function_Name(Parameter_1, Parameter_2) {
console.log(Parameter_1, Parameter_2)
}
}
</script>
Hopefully this helps you out!

Method not changing variable

I'm creating a app that will be accessing the user's webcam. I want to the change the error variable to the error message if navigator.getUserMedia fails. This should outputting the error message, but instead it's outputting stream. I'm very new to Vue so pardon me if I'm missing something very obvious
my code is as follows
<template>
<div class="">
<h1 v-if="error === null">
Stream
</h1>
<h1 v-else>
{{ error }}
</h1>
</div>
</template>
<script>
export default {
data () {
return {
error: null
}
},
methods: {
setUnsupported () {
this.error = 'Your browser does not support video :('
}
},
ready () {
this.setUnsupported()
if (navigator.getUserMedia) {
} else {
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
If you are using Vue 2.0, ready has been replaced with mounted. Please check the documentation here.
....
mounted () {
this.setUnsupported()
}
....

Polymer - <iron-ajax> data binding

I have created a polymer element and inside the element I am fetching a small little .json file that I will need to use for various parameters.
My JSON file looks like this.
{
"server_name" : "XMS Development Site",
"server_url" : "test0",
"xms_version" : "3.0.0 BETA",
"rest": {
"os_url" : "test1",
"mbo_url": "test2",
"login_url": "test3",
"logout_url": "test4",
}
}
I am unable to access the values in this JSON object from my iron-ajax request. The {{response.xms_version}}binding just appears blank. The on-response function just displays null. Looking in chrome's dev tools, the JSON file is retrieved and the data is all there. It seems that for some reason I am just unable to bind to it. I am not trying to use the dom-repeat method as I just need to be able to bind to these data points.
My element looks like this:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="xms-login">
<template>
<style>
:host {
display: block;
}
.login-form-button{
padding: 16px;
text-align: center;
}
.login-form{
}
.login-field{
padding-top: 16px;
padding-left: 16px;
padding-right: 16px;
}
.login-button{
background-color: var(--default-primary-color);
color: var(--text-primary-color);
}
.xms-logo-svg{
text-align: center;
padding-top: 64px;
}
.version-number-text{
text-align: center;
postion: absolute;
bottom: 0;
}
</style>
<iron-ajax id="testAjax" auto
url="../../xms.json"
handle-as="json"
method="GET"
on-response="handleResponse"
last-response="{{response}}"></iron-ajax>
<xms-auth id="xmsAuthHandler" authheader="{{computeEncodedLogin(username, password)}}" provider="rest"></xms-auth>
<div class="login-form">
<div class="login-form-fields">
<paper-input class="login-field" type="text" label="Username" value="{{username}}"></paper-input>
<paper-input class="login-field" type="password" label="Password" value="{{password}}"></paper-input>
</div>
<div class="login-form-button">
<paper-button raised class="login-button" onclick="xmsAuthHandler.login()">Login</paper-button>
</div>
<div class="version-number-text">{{response.xms_version}}</div>
</div>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'xms-login',
properties: {
user: {
type: String,
notify: true
},
username: {
type: String,
notify: true
},
password: {
type: String,
notify: true
},
},
computeEncodedLogin: function( username, password ){
return btoa(username + ':' + password);
},
handleResponse: function(request){
var myResponse = request.detail.response;
console.log(myResponse);
}
});
})();
</script>
</dom-module>
Issue is fixed, was caused by incorrect JSON data.

Polymer add Html tags with properties

My Polymer element displays some properties it gets passed as attributes. The content property may contain some html tags like <br> or <p>. The problem I'm facing with, is, that Polymer doesn't add the tags to the DOM tree, instead it prints them like normal text. Is there a way to force "DOM tree adding"?
The whole element:
<link rel="import" href="paper-toolbar/paper-toolbar.html">
<link rel="import" href="iron-collapse/iron-collapse.html">
<link rel="import" href="paper-material/paper-material.html">
<dom-module id="card-element" is="auto-binding">
<style>
#contentWrapper {
padding: 10px 15px;
}
#toolbar {
--paper-toolbar-background: #607D8B;
--paper-toolbar: {
font-size: 125%;
opacity: 0.9;
};
}
.maxWidth {
width: 100%;
}
</style>
<template>
<paper-material elevation="2" class="maxWidth" id="card" animatedShadow="1">
<paper-material elevation="1" class="maxWidth">
<paper-toolbar on-click="toggleCollapse" id="toolbar" justify="justified">
<span class="title">{{convertedDate}}</span><span class="title">{{fach}}</span>
</paper-toolbar>
</paper-material>
<iron-collapse id="collapse">
<div id="contentWrapper">
<span>{{content}}</span>
</div>
</iron-collapse>
</paper-material>
</template>
<script>
Polymer({
is: "card-element",
properties: {
opened: {
type: Boolean,
value: false
},
fach: {
type: String,
value: "u-oh an Error"
},
content: {
type: String,
value: "u-oh an Error"
}
},
toggleCollapse: function() {
if(this.opened) {
this.$.collapse.hide();
this.$.card.elevation = "2";
this.opened = false;
}
else {
this.$.collapse.show();
this.$.card.elevation = "5";
this.opened = true;
}
},
ready: function() {
var date = new Date(this.datum);
this.convertedDate = date.getDate() + "." + (date.getMonth() + 1) + "." + date.getFullYear();
}
});
</script>
</dom-module>
Polymer not allowed html to prevent XSS attack
But you can do this
<dom-module id="html-echo">
<style>
:host {
display: block;
}
</style>
<template>
</template>
</dom-module>
<script>
(function () {
Polymer({
is: 'html-echo',
properties: {
html: {
type: String,
observer: '_htmlChanged'
}
},
_htmlChanged: function (neo) {
// WARNING: potential XSS vulnerability if `html` comes from an untrusted source
this.innerHTML = neo;
}
});
})();
</script>
Use like
<html-echo html="[[htmlText]]"></html-echo>

How to make a list of modifiable object in Polymer

Here is the host element.
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../common-settings-service/common-settings-service.html">
<link rel="import" href="../bower_components/paper-button/paper-button.html"/>
<link rel="import" href="../bower_components/paper-material/paper-material.html"/>
<link rel="import" href="../bower_components/iron-list/iron-list.html">
<link rel="import" href="../bower_components/iron-flex-layout/iron-flex-layout.html">
<dom-module id="common-settings">
<style>
:host {
display: block;
}
paper-material {
background: #FFFFFF;
}
.container {
#apply(--layout-horizontal);
}
.windowItem {
#apply(--layout-horizontal);
}
.list {
#apply(--layout-flex);
#apply(--layout-vertical);
}
.item {
#apply(--layout-horizontal);
margin: 16px 16px 0 16px;
padding: 20px;
border-radius: 8px;
background-color: white;
border: 1px solid #ddd;
}
</style>
<template>
<common-settings-service
id="commonSettings"
url="/board_service/common_settings/"
settings="{{settings}}"></common-settings-service>
<paper-material elevation="1">
<div>
<h3> Настройки обработки</h3>
<h4>Окна</h4>
<iron-list items="{{settings.timeWindows}}" as="item">
<template>
<div>
<paper-input type="number"
value="{{item}}" label="Размер окна"></paper-input>
<paper-button raised on-tap="removeWindow">Удалить</paper-button>
</div>
</template>
</iron-list>
<!--<template is="dom-repeat" items="{{settings.timeWindows}}">-->
<!--<div class="windowItem">-->
<!--<paper-input type="number"-->
<!--value="{{item}}" label="Размер окна"></paper-input>-->
<!--<paper-button raised on-tap="removeWindow">Удалить</paper-button>-->
<!--</div>-->
<!--</template>-->
<paper-button raised on-tap="addWindow">Добавить</paper-button>
<paper-input type="number"
value="{{settings.signalUpperLimit}}"
label="Верхнее ограничение сигнала"></paper-input>
<paper-input type="number"
value="{{settings.signalLowerLimit}}"
label="Нижнее ограничение сигнала"></paper-input>
<paper-input type="number"
value="{{settings.accumulationTimeSeconds}}"
label="Время накопления в секундах"></paper-input>
<paper-input type="string"
value="{{settings.serverIp}}"
label="IP адрес сервера обработки"></paper-input>
<paper-input type="number"
value="{{settings.thresholdProcessingSettings.windowSize}}"
label="Размер окна для фильтрации порогов"></paper-input>
<paper-input type="number"
value="{{settings.thresholdProcessingSettings.thresholdLowerLimit}}"
label="Нижнее ограничение порогов"></paper-input>
<paper-input type="number"
value="{{settings.thresholdProcessingSettings.thresholdUpperLimit}}"
label="Верхнее ограничение порогов"></paper-input>
<paper-input type="number"
value="{{settings.activeChannelsLimitPercent}}"
label="Ограничение на сработавшие каналы в процентах"></paper-input>
</div>
</paper-material>
</template>
</dom-module>
<script>
Polymer({
is: 'common-settings',
removeWindow: function () {
this.$.commonSettings.removeWindow(20);
},
addWindow: function () {
this.$.commonSettings.addWindow(20);
console.log(this.$.commonSettings.settings.timeWindows);
}
});
</script>
And here is child element
<link rel="import" href="../bower_components/polymer/polymer.html">
<script>
Polymer({
is: 'common-settings-service',
behaviors: [MyBehaviors.DefaultServiceBehavior],
properties: {
settings: {
type: Object,
notify: true,
value: {
segments: [
{
first_index: 0,
last_index: 960
}
],
timeWindows: [10],
signalUpperLimit: 100,
signalLowerLimit: -100,
accumulationTimeSeconds: 600.0,
serverIp: "127.0.0.1",
thresholdProcessingSettings: {
windowSize: 10,
thresholdLowerLimit: -100,
thresholdUpperLimit: 100
},
activeChannelsLimitPercent: 10.0
}
}
},
getSettingsFromResponse: function (response) {
return response._embedded.commonSettingses[0];
},
removeWindow: function (size) {
var index = this.settings.timeWindows.indexOf(size);
this.pop('settings.timeWindows', index);
},
addWindow: function(size) {
this.push('settings.timeWindows', size);
}
});
</script>
I can add and remove elements (while I don't know right now how to remove specific element) from array and I can see that it's removed from list also. But when I change value in field this change isn't reflected in bounded list element. How can I change that?
Put set(path, value) in on-change event, e.g.:
<paper-input on-change="update_property"
id="settings.signalUpperLimit"
type="number"
value="{{settings.signalUpperLimit}}"
label="Верхнее ограничение сигнала"></paper-input>
Inside update_property do change the value:
update_property: function(e, detail, sender) {
// from sender: take the new value and it's id.
console.log(sender);
var id = sender.id;
//... take the new value
// locate the property path in the array and change it
//... set(path, value)
}

Categories