Modify iron-form JSON before submitting - json

I'm wondering if it is possible to edit the JSON file of an iron-form before submitting it? For instance, if I want to add an array which doesn't come from any of the form input, or if I want to add a unique key in it...
If it is possible, I believe it would be during the form pre-submit, but the documentation says nothing about "how to intercept the JSON" or something like that.
Thanks!

You could modify the iron-form's request object in the iron-form-presubmit event handler. For POST requests, the form data is stored in the body, which you would access by this.$.form.request.body. For other request types, the data is in this.$.form.request.params. This example adds an array to the request's body:
// template
<form is="iron-form" id="form" on-iron-form-presubmit="_presubmit" method="post">...</form>
// script
_presubmit: function(e) {
var body = this.$.form.request.body;
body['newkey'] = [1,2,3];
console.log('body', body);
},
<head>
<base href="https://polygit.org/polymer+1.11.3/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="iron-form/iron-form.html">
<link rel="import" href="paper-input/paper-input.html">
<link rel="import" href="paper-button/paper-button.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<form is="iron-form" id="form" on-iron-form-presubmit="_presubmit" method="post" action="//httpbin.org/post">
<paper-input name="name" label="name"></paper-input>
<paper-button on-tap="_submit">Submit</paper-button>
</form>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-foo',
_presubmit: function(e) {
var body = this.$.form.request.body;
body['newkey'] = [1,2,3];
console.log('body', body);
},
_submit: function() {
this.$.form.submit();
}
});
});
</script>
</dom-module>
</body>
codepen

Related

Polymer 2.0 - Trying to create HTML template from JSON with events

I am trying to create HTML templates from JSON object and able to render elements but the events are not getting added to the element and not showing up in the developer tools/Shadow DOM.
Codepen for reference - https://codepen.io/nagasai/pen/bRjWbd
Issue: Events - onkeypress, onkeyup,onchange are not showing on input and checkbox elements and couldn't add them but other options are showing up like name, type(Again type is getting displayed only for checkbox but not for textbox)
Screenshot for actual issue
HTML:
<head>
<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="iron-collapse/iron-collapse.html">
</head>
<body>
<x-foo attr='[{
"type":"text",
"title":"Textbox Name",
"name":"temp",
"requried":"requried",
"onkeypress":"testKeyPress()",
"onkeyup":"testKeyUp()",
"onchange":""
},{
"type":"checkbox",
"title":"CheckBox Name",
"name":"temp",
"requried":"requried",
"disabled":"disabled",
"onkeypress":"",
"onkeyup":"",
"onchange":"testChange()"
}]'></x-foo>
<dom-module id="x-foo">
<template>
<template is="dom-repeat" items="{{attr}}">
<label>{{item.title}}</label>
<input type="{{item.type}}"
required="{{item.required}}"
name="{{item.name}}"
onchange="{{item.onchange}}"
onkeypress="{{item.onkeypress}}"
onkeyup="{{item.onkeyup}}()"
>
</template>
</template>
</dom-module>
</body>
JS:
class XFoo extends Polymer.Element {
static get is() { return 'x-foo'; }
static get properties() {
return {
attr:{
type:Array
}
};
}
}
customElements.define(XFoo.is, XFoo);
Correct me if I'm wrong but it should be:
on-change="{{item.onchange}}"
on-keypress="{{item.onkeypress}}"
on-keyup="{{item.onkeyup}}()"
Reference: https://www.polymer-project.org/2.0/docs/devguide/gesture-events

reading json and converting to HTML - polymer

I am trying to read local json file and convert it to HTML layout
I was able to read JSON from local but struggling to read and render on UI
HTML:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.rawgit.com/download/polymer-cdn/1.5.0/lib/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="https://cdn.rawgit.com/download/polymer-cdn/1.5.0/lib/polymer/polymer.html">
<link rel="import" href="https://cdn.rawgit.com/download/polymer-cdn/1.5.0/lib/iron-ajax/iron-ajax.html">
</head>
<body>
<template is="dom-bind">
<iron-ajax
auto
url="properties.json"
last-response="{{data}}"
handle-as="json">
</iron-ajax>
<div><span>{{data}}</span></div>
<!-- <template is="dom-repeat" items="{{data}}">
<div><span>{{item.name}}</span></div>
</template> -->
</template>
<script>
(function (document) {
'use strict';
var app = document.querySelector('#app');
window.addEventListener('WebComponentsReady', function() {
var ironAjax = document.querySelector('iron-ajax');
ironAjax.addEventListener('response', function() {
console.log(ironAjax.lastResponse);
});
ironAjax.generateRequest();
});
})(document);
</script>
</body>
</html>
properties.json file
{
"main":{
"header":{
"label" :"Employee Template",
"logo":"abc.png"
},
"footer":{
"label" :"2017 All rights reserved.",
"author":"abc"
},
"menu":[
{
"label":"Add",
"url":"/Add"
},
{
"label":"Delete",
"url":"/Delete"
}
]
}
I am trying to render the above json as below HTML
<header><h1>{{Employee.header.label}}</h1>
<img src={{Employee.header.logo}}>
</header>
<ul>
<li>{{Employee.menu[0].label}}</li>
<li>{{Employee.menu[0].label}}</li>
</ul>
<footer><h1>{{Employee.footer.label}}</h1>
<div>{{Employee.footer.author}}></div>
</footer>
I tried iron-ajax for rendering, but it works only on array of objects and not reading through the json and didnt find much information on documentation
At first, you are propably missing main in all bindings? according to your json the hiearchy is main.header.label and not header.label.
Another issue: When you are pointing to some index of array in bindings you are using {{Employee.menu[0].label}} but it should be {{Employee.menu.0.label}}. Remember this, because once you will use array mutation methods, it will be same.
If your JSON's structure is always like that and never changes, then it's super simple and you have already did, what you wanted. If your JSON's structure can change to something more complex, then you will have to propably write your own parser. which means, iterating all keys insinde json, creating elements and putting content in it. It will be a little bit harder, but it is possible.
I don't know how your json can look like so i won't write you parser. You will have to try it on your own.
It will start something like:
for(var key in this.Employee.main) {
var el = document.createElement(key);
...
}
here is an fiddle with an working example of your code: fiddle
The fiddle is ab bit different since i have no clue how to do ajax in fiddle but your code sould look like this:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.rawgit.com/download/polymer-
cdn/1.5.0/lib/webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="https://cdn.rawgit.com/download/polymer-
cdn/1.5.0/lib/polymer/polymer.html">
<link rel="import" href="https://cdn.rawgit.com/download/polymer-
cdn/1.5.0/lib/iron-ajax/iron-ajax.html">
</head>
<body>
<template is="dom-bind">
<iron-ajax
auto
url="properties.json"
last-response="{{data}}"
handle-as="json">
</iron-ajax>
<header><h1>{{Employee.header.label}}</h1>
<img src={{Employee.header.logo}}>
</header>
<ul>
<li>{{data.main.menu.0.label}}</li>
<li>{{data.main.menu.0.label}}</li>
</ul>
<footer><h1>{{data.main.footer.label}}</h1>
<div>{{data.main.footer.author}}></div>
</footer>
</template>
<script>
(function (document) {
'use strict';
var app = document.querySelector('#app');
window.addEventListener('WebComponentsReady', function() {
var ironAjax = document.querySelector('iron-ajax');
ironAjax.addEventListener('response', function() {
console.log(ironAjax.lastResponse);
});
ironAjax.generateRequest();
});
})(document);
</script>
</body>
</html>`

Iron ajax not working

I'm trying to get iron-ajax working but thus far without success.
I have added the component to my bower.json, ran bower install, imported it in the html file I want it to use in and tried to add it to a template.
Usually my IDE auto-completes all Polymer tags just fine but this one just won't work. When I open the page I get the following error: Uncaught ReferenceError: Invalid left-hand side in assignment which points to the " this.$.add-contact.contentType = "application/json";" line, see below.
I am wondering if the element is properly imported or if I'm missing something obvious.
Here's my code:
<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="contact-form">
<template>
<style>
</style>
<h1>My New Contact</h1>
<paper-input label="Name" value="{{name}}"></paper-input>
<paper-input label="Phone Number:" value="{{telnr}}"></paper-input>
<paper-button on-tap="addContact">Add Contact</paper-button>
<iron-ajax id="add-contact"
method="POST"
url="/cgi-bin/add-contact.py"
handle-as="json"
on-response="addContact_ResponseHandler">>
</iron-ajax>
</template>
<script>
Polymer({
is: "contact-form",
addContact: function () {
this.$.add-contact.contentType = "application/json";
this.$.add-contact.body = {naam: this.name, telnr: this.telnr};
this.$.add-contact.generateRequest();
console.log("Contact: " + this.name+ ", " + this.telnr);
}
addContact_ResponseHandler:
function(request_confirm) {
console.log("Response: " + request_confirm);
}
});
</script>
</dom-module>
this.$.add-contact is actually equivalent to this.$.add - contact (a subtraction of a symbol named contact from the element with an ID of add (neither of which exist).
To access <iron-ajax id="add-contact"> imperatively, use this.$['add-contact'].

Polymer 1.x: accessing element within dom-if

Here is my JSBin
Click on the "First Name: James" text.
I have an input element within dom-if. In an event, I am making dom-if to pass and so the element will come into existence but I cannot access the input element immediately after making the dom-if condition pass.
May be I need to know when the dom-if is actually evaluated and why the element does not exist even if the condition has become true.
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="iron-form/iron-form.html" rel="import">
<link href="paper-input/paper-input.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style></style>
<template is="dom-if" if="{{!editMode}}">
<span id="name" on-tap="_makeEditable">{{name}}: {{value}}</div>
</template>
<template is="dom-if" if="{{editMode}}">
<paper-input id="input" label="{{name}}" value="{{value}}"></paper-input>
</template>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {
editMode: {
type: Boolean,
value: false
},
name: {
type:String,
value:"First Name"
},
value: {
type:String,
value:"James"
}
},
_makeEditable: function() {
this.editMode = true;
//how to find the input element here
//this.$$('#input').querySelector("input").focus();
//this.$.input.querySelector("input").focus();
}
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
This is because setting this.editMode to true does not update the DOM instantaneously.
You should be running your selector asynchronously, so that Polymer has some time to update the DOM, such as:
this.async(function() {
this.$$('#input').focus();
})
Fiddle here.

iron-data-table selected-item throws 'null' when currently selected item is selected again

In iron-data-table, when I click any currently selected row, I expect the selected-item ({{selectedItem}}) object to reflect the currently (and previously) selected row; but instead, it becomes null.
Steps to recreate the problem:
Open this jsBin.
Select any row.
Notice selected object prints to top of page and to console.
Select a different row.
Notice newly selected item prints to top of page and to console.
Clear console. (Optional. Will help you see results of next step.)
Click currently selected row.
Notice selected-item ({{selectedItem}}) object is now null.
How can I correct this so the selected object is the newly selected row (which is the previously selected row) and not null?
http://jsbin.com/xucemijada/1/edit?html,console,output
<!DOCTYPE html>
<html>
<head>
<base href="https://polygit.org/polymer+:master/iron-data-table+Saulis+:master/components/">
<link rel="import" href="polymer/polymer.html">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="iron-ajax/iron-ajax.html">
<link rel="import" href="paper-button/paper-button.html">
<link rel="import" href="iron-data-table/iron-data-table.html">
<link rel="import" href="iron-data-table/default-styles.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<style>
</style>
[[_computeSelectedStr(selectedItem)]]
<iron-ajax
auto
url="https://saulis.github.io/iron-data-table/demo/users.json"
last-response="{{users}}"
>
</iron-ajax>
<iron-data-table id="grid"
selection-enabled
items="[[users.results]]"
selected-item="{{selectedItem}}"
>
<data-table-column name="Picture" width="50px" flex="0">
<template>
<img src="[[item.user.picture.thumbnail]]">
</template>
</data-table-column>
<data-table-column name="First Name">
<template>[[item.user.name.first]]</template>
</data-table-column>
<data-table-column name="Last Name">
<template>[[item.user.name.last]]</template>
</data-table-column>
<data-table-column name="Email">
<template>[[item.user.email]]</template>
</data-table-column>
</iron-data-table>
</template>
<script>
(function(){
'use strict';
Polymer({
is: 'x-foo',
observers: [
'_selectedItemChanged(selectedItem)' ,
],
_selectedItemChanged: function(ob) {
console.log('selectedItem', ob);
},
_computeSelectedStr: function(ob) {
return JSON.stringify(ob);
},
});
})();
</script>
</dom-module>
</body>
</html>
When a row is clicked a second time, the item gets deselected and having null in selectedItem is meant to reflect that. Similarly, in multi-select mode selectedItems is empty when nothing is selected.
Since v1.0.1 <iron-data-table> will fire deselecting-item event which can be used to prevent deselection.
table.addEventListener('deselecting-item', function(e) {
e.preventDefault();
});
I've updated your JSBin to show an example how to use this event: http://jsbin.com/dubuyoy/edit?html,console,output