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.
Related
If I do this on vue:
<input pattern="\d+">
It gets properly validated, but I get a popup with a message "Please match the requested format".
Is there any way to change this message? I can't find the documentation on the accepted validation tags.
JSFiddle: http://jsfiddle.net/ovz5p3wt/
so, as noted in comments, the way to do it is to use oninvalid and setCustomValidity
<input pattern="\d+" oninvalid="setCustomValidity('please use a number')">
However, if you want to do it using a script (since you are tagging at as vue) here is another solution that allows you to dynamically change the value you can use the script version. unfortunately #oninvalid doesn't seem to be supported by vue, so you'd need to set the functionality using $refs
updateCustomValidity(lang){
var el = this.$refs.el;
el.oninvalid = el.setCustomValidity(this[lang].message);
}
new Vue({
el: "#app",
data() {
return {
lang: 'en',
en: {
message: 'nope, sorry',
},
fr: {
message: 'sacre bleu'
}
}
},
watch: {
lang: {
handler(lang) {
this.updateCustomValidity(lang);
}
}
},
methods: {
updateCustomValidity(lang){
var el = this.$refs.el;
el.oninvalid = el.setCustomValidity(this[lang].message);
}
},
mounted() {
this.updateCustomValidity(this.lang);
}
})
body { background: #20262E; padding: 20px; font-family: Helvetica;}
#app { background: #fff; border-radius: 4px; padding: 20px; transition: all 0.2s;}
input { margin: 8px 0;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
EN: <input type="radio" v-model="lang" value="en">
FR: <input type="radio" v-model="lang" value="fr">
<form>
<input pattern="\d+" value="text" ref="el">
<button type="submit">Submit</button>
</form>
</div>
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()
}
....
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>
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)
}
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.