i am working on a custom element that will serve as a form for sending map node data to a database using a restful service.
i have 3 questions about this element.
can this even work? i am trying to use a method which seems exactly the opposite of the direct data binding method when collecting data from a server. can this be used for sending to the server.
in the core-ajax element i am using the auto="false" attribute. how would i go about calling the go() command when a use clicks the paper-button?
if this method for sending can work how do i catch the body="{}" line in php when submitted? i know it isn't sent as a $_GET. is it sent as $_POST or do i need to use another method to catch it?
my element template currently looks like
<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/core-ajax/core-ajax.html">
<polymer-element name="add-node" attributes="url">
<template>
<style>
paper-input {
color:#000000;
text-align:left;
}
paper-button.colored {
background:#000000;
color:#ffffff;
}
.centered {
display:block;
text-align:center;
width:100%;
}
</style>
<geo-location latitude="{{lat}}" longitude="{{lng}}"></geo-location>
<form id="form_1">
<paper-input floatingLabel label="Name:" value="{{name}}"></paper-input>
<br>
<paper-input floatingLabel label="Street Address:" value="{{address}}"></paper-input>
<br>
<paper-input floatingLabel label="City" value="{{city}}"></paper-input>
<br>
<paper-input floatingLabel label="State" value="{{state}}"></paper-input>
<br>
<paper-input floatingLabel label="Zip" value="{{zip}}"></paper-input>
<br>
<paper-input floatingLabel label="Phone:" value="{{phone}}"></paper-input>
<br>
<paper-input floatingLabel label="Description:" value="{{description}}"></paper-input>
<br>
<div class="centered">
<paper-button on-tap="{{doSend}}" raisedButton class="colored" label="Save"></paper-button>
</div>
</form>
<core-ajax id="ajax" auto="false" method="POST" contentType="application/json" url="{{url}}"
body='{"name":"{{name}}", "address":"{{address}}", "city":"{{city}}", "state":"{{state}}", "zip":"{{zip}}", "phone":"{{phone}}", "description":"{{description}}", "longitude":"{{lng}}", "latitude":"{{lat}}"}' response="{{response}}">
</core-ajax>
<template repeat="{{response}}">{{data}}</template>
</template>
<script>
Polymer('add-node', {
doSend: function(event, detail, sender){
this.$.ajax.go();
}
});
</script>
</polymer-element>
It should work just OK. To invoke the go() give your ajax element an id so it is easy to access, ie
<core-ajax id="foobar" auto="false" ...></core-ajax>
attach an eventhandler to the button
<paper-button ... on-tap="{{doSend}}"></paper-button>
and implement the doSend() handler in your elements script section (do not forget to get rid of the noscript in the elements declaration)
<script>
Polymer('add-node', {
doSend: function(event, detail, sender){
this.$.foobar.go();
}
});
</script>
As of proccessing the data at server side - yes, you should look for the data in the $_POST.
A couple of notes:
Instead of assembling data at send time, it's probably convenient to treat the data as an object in the first place. I called it item (it could be record or node or whatever) and I made it bindable so you could pass in a record for editing.
body is generally for sending data that you format yourself. In this, case since you have normal name='value' pairs that you want to access as such in PHP, use params instead. At that point either GET or POST will work (POST is usually better).
Updated example:
<polymer-element name="add-node" attributes="url item">
<template>
<style>
paper-input {
color:#000000;
text-align:left;
}
paper-button.colored {
background:#000000;
color:#ffffff;
}
.centered {
display:block;
text-align:center;
width:100%;
}
</style>
<geo-location latitude="{{lat}}" longitude="{{lng}}"></geo-location>
<form id="form_1">
<paper-input floatingLabel label="Name:" value="{{item.name}}"></paper-input>
<br>
<paper-input floatingLabel label="Street Address:" value="{{item.address}}"></paper-input>
<br>
<paper-input floatingLabel label="City" value="{{item.city}}"></paper-input>
<br>
<paper-input floatingLabel label="State" value="{{item.state}}"></paper-input>
<br>
<paper-input floatingLabel label="Zip" value="{{item.zip}}"></paper-input>
<br>
<paper-input floatingLabel label="Phone:" value="{{item.phone}}"></paper-input>
<br>
<paper-input floatingLabel label="Description:" value="{{item.description}}"></paper-input>
<br>
<div class="centered">
<paper-button on-tap="{{doSend}}" raisedButton class="colored" label="Save"></paper-button>
</div>
</form>
<core-ajax id="ajax" method="POST" url="{{url}}" params="{{item}}" response="{{response}}"></core-ajax>
<template repeat="{{response}}">{{data}}</template>
</template>
<script>
Polymer('add-node', {
created: function() {
this.item = {};
},
doSend: function() {
this.$.ajax.go();
}
});
</script>
</polymer-element>
Related
Polymer 1.*
Is there a way to place a value other than the text in paper item that is used inside a paper-dropdown? For instance, when form is submitted I would like 50 instead of $50 dollars. I tried placing value='50' but the form still used the text $50 dollars.
<paper-dropdown-menu label="minimumPrice" name="minimumPrice">
<paper-listbox class="dropdown-content" selected="0">
<paper-item>No min</paper-item>
<paper-item>$50 dollars</paper-item>
There might be no official way to do that, but you could still technically accomplish your goal (with somewhat of a hack).
<paper-dropdown-menu> has an observer on its selectedItem that sets both its value and label to the same value (derived from the selected item); and the selectedItem is set by the <paper-dropdown-menu>'s event listener on iron-select, so you could add your own listener that overrides the label.
Here are the steps:
Specify the desired item value on each <paper-item>'s label attribute. Note the <paper-dropdown-menu> sets its value to the label of the selected item, but the text content of the <paper-item> still appears in the open dropdown menu (i.e., the listbox).
<paper-item label="0">No min</paper-item>
<paper-item label="50">$50 dollars</paper-item>
Add a listener for the iron-select event from <paper-dropdown-menu> in order to override the displayed label for the selected item.
ready: function() {
// <paper-dropdown-menu id="menu">
this.$.menu.addEventListener('iron-select', (e) => {
const paperItem = e.detail.item;
this.$.menu._setSelectedItemLabel(paperItem.textContent.trim());
});
}
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
_onResponse: function(e) {
const resp = e.detail.response;
this.response = JSON.stringify(resp, null, 2);
},
ready: function() {
this.$.menu.addEventListener('iron-select', (e) => {
const paperItem = e.detail.item;
this.$.menu._setSelectedItemLabel(paperItem.textContent.trim());
});
}
});
});
<head>
<base href="https://polygit.org/polymer+1.10.1/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="neon-animation/web-animations.html">
<link rel="import" href="iron-form/iron-form.html">
<link rel="import" href="paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="paper-listbox/paper-listbox.html">
<link rel="import" href="paper-item/paper-item.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<iron-form id="myForm" on-iron-form-response="_onResponse">
<form action="https://httpbin.org/get">
<paper-dropdown-menu id="menu" label="Minimum Price" name="minimumPrice">
<paper-listbox slot="dropdown-content" class="dropdown-content">
<paper-item label="0">No min</paper-item>
<paper-item label="50">$50 dollars</paper-item>
<paper-item label="100">$100 dollars</paper-item>
<paper-item label="200">$200 dollars</paper-item>
</paper-listbox>
</paper-dropdown-menu>
<button type="submit">Submit</button>
</form>
</iron-form>
<pre>[[response]]</pre>
</template>
</dom-module>
</body>
codepen
Try
<paper-item value="50" selected>$50 dollars</paper-item>
This would select the $50 dollars as default and should grab the value
You can add label property in paper-item to get the desired result.
<paper-dropdown-menu label="minimumPrice" name="minimumPrice">
<paper-listbox id="test" slot="dropdown-content" class="dropdown-content" selected="0">
<paper-item label="0">No min</paper-item>
<paper-item label="50">$50 dollars</paper-item>
</paper-listbox>
</paper-dropdown-menu>
The value property in paper-dropdown-menu will always have the same value as of selectedItemLabel and the selectedItemLabel contains the value derived from the "label" of the currently selected item if set, or else the trimmed text content of the selected item.
Update
Another way:
Create a hidden input and assign the selected value to the hidden input's value.
<paper-dropdown-menu label="minimumPrice" >
<paper-listbox slot="dropdown-content" class="dropdown-content" selected="{{selected}}" attr-for-selected="value">
<paper-item value="0">No min</paper-item>
<paper-item value="50">$50 dollars</paper-item>
</paper-listbox>
</paper-dropdown-menu>
<input is="iron-input" name="minimumPrice" id="hiddenSelected" type="hidden" value="[[selected]]">
And if you want first content to be selected by default you can assign inside ready function:
ready: function(){
this.selected = 0;
}
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'].
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
I have a form with several input fields and checkbox. I can shift focus through the input fields and checkboxes. But the "SAVE" paper-button at the page wont get focus at all. User needs to use a mouse to click the paper-button.
How to make paper-button focusable?
Tabbing seems to work fine for me with the following code:
<head>
<title>Hello</title>
<base href="http://element-party.xyz/">
<link rel="import" href="all-elements.html">
</head>
<body>
<dom-module id="element-name">
<template>
<paper-input label="input 1"></paper-input>
<paper-input label="input 2"></paper-input>
<paper-input label="input 3"></paper-input>
<paper-input label="input 4"></paper-input>
<paper-input label="input 5"></paper-input>
<paper-checkbox>Checkbox</paper-checkbox>
<paper-button>Button</paper-button>
</template>
<script>
Polymer({
is: "element-name"
});
</script>
</dom-module>
<element-name></element-name>
</body>
</html>
Can you provide some code showing your problem?
I am am trying to create a custom element that plays a youtube video in paper-dialog. So videoPlayer = Polymer.dom(this.root).querySelector('video-player'); inherits/has access to that paper-dialogs open method, I am trying to extend my custom element. It isn't working, but hopefully I am on the right track and someone can show me correctly.
I am using Polymer 1.0, but I only have https://www.polymer-project.org/0.5/docs/polymer/polymer.html#extending-other-elements to go by for extending elements.
<link rel="import" href="../bower_components/paper-dialog/paper-dialog.html">
<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../bower_components/google-youtube/google-youtube.html">
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id="video-player">
<template>
<div class="layout horizontal">
<paper-button dialog-dismiss>
<paper-icon-button icon="arrow-back"></paper-icon-button>
</paper-button>
</div>
<div style="height: 100%; width: 100%">
<google-youtube style="height: 100%;"
video-id="YMWd7QnXY8E"
rel="1"
start="5"
playsinline="0"
controls="2"
showinfo="0"
width="100%"
height="100%"
autoplay="1">
</google-youtube>
</div>
</template>
<script>
Polymer({
is: "video-player"
});
</script>
<paper-dialog name="video-player" extends="video-player">
<template>
<shadow></shadow>
</template>
<script>
Polymer();
</script>
</paper-dialog>
<video-player></video-player>
As was mentioned in the comments, you can't yet extend custom elements, so the existing pattern (or at least the one I use) is to make use of behaviors wherever possible and wrappers wherever not.
e.g.
<dom-module id="popup-video-player">
<template>
<video-player></video-player>
</template>
<script>
Polymer({
is: 'popup-video-player',
behaviors: [Polymer.PaperDialogBehavior],
...
});
</script>
</dom-module>
Now you can use <popup-video-player> just like a paper-dialog.
I know it stinks because if video-player has a bunch of properties that you want access to, you have to copy them in the popup-video-player element's API, which is not exactly DRY.
If you look at the paper-input source, you'll see them doing the same thing. It's obvious that they want to extend iron-input, but they can't so you get things like this:
<input is="iron-input" id="input"
aria-labelledby$="[[_ariaLabelledBy]]"
aria-describedby$="[[_ariaDescribedBy]]"
disabled$="[[disabled]]"
title$="[[title]]"
... >
As a side note, you could always hook into the <video-player>s "properties" property and make the API additions programatically.
maybe something like this would work: (untested!)
Polymer({
...
properties: (function () {
var prop = {
//special properties specific to the pop up version of video-player
//..obviously be careful to avoid name space conflicts.
};
var video_player = document.createElement('video-player');
video_player.properties.keys().forEach( function(key) {
props[key] = video_player[key];
});
return props;
}()),
});