I have a custom element using iron-ajax. I don't know why the request occurs twice. This is my code:
<template>
<div style="text-align: center" hidden="{{!cargando}}">cargando ... <br />
<paper-spinner alt="cargando ..." active="[[cargando]]"></paper-spinner>
</div>
<ficha-folleto datos="[[ajaxResponse]]"></ficha-folleto>
<iron-ajax
auto
url="backend/api.php?operacion=folleto&idf=[[idf]]&len=[[len]]"
handle-as="json"
verbose=true
last-response={{ajaxResponse}}
loading="{{cargando}}"> </iron-ajax>
</template>
<script>
Polymer({
is: "folleto-digital",
properties: {
}
});
</script>
The call is from this page:
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="elements/folleto-digital/folleto-digital.html">
<!DOCTYPE html>
<html>
<head>
<script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<folleto-digital idf="" id="folleto"></folleto-digital>
<script src="js/funciones.js"></script>
<script>
var idf = getParameterByName("idf");
var folleto = document.querySelector("#folleto");
folleto.idf = idf;
var len = getParameterByName("len");
folleto.len = len;
</script>
</body>
</html>
And I'm requesting this url: folleto.html?idf=1&len=es
All is working fine, but there are two request:
api.php?operacion=folleto&idf=&len=
api.php?operacion=folleto&idf=1&len=es
The Polymer documentation says about auto param:
"If true, automatically performs an Ajax request when either url or params changes"
So I think the param at the begining have value="" and then take the values from the querystring and because of that request twice.
How can I fix this to do one and only one request?
Thanks!
When <iron-ajax>.auto is true, the element automatically generates the request if the url is a non-empty string. Since the url has a non-empty value even when idf and len are blank/empty, the <iron-ajax> generates a request even before you've set idf and len.
If you want <iron-ajax> to send the request only when idf and len are set, you'd need to remove auto, and add a complex observer on idf and len that generates the request only when both values are not empty.
// template
<iron-ajax id="ajax" ...>
Polymer({
is: "folleto-digital",
properties: {
idf: String,
len: String
},
observers: ['_sendRequest(idf, len)'],
_sendRequest: function(idf, len) {
if (idf && len) {
this.$.ajax.generateRequest();
}
}
});
Related
I have a very simple polymer 2 app, which uses query query string parameters. Moving to Polymer 2.0.1 and app-location 2.0 (instead of rc and preview versions), I noticed that simply having an app-location element deletes all query string parameters from the url.
Try this url: https://api-1913.s3-eu-west-1.amazonaws.com/index.html?foo=bar, and notice how the query string is removed during loading.
Here's all the code:
index.html:
<!DOCTYPE HTML>
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="/my-app.html">
<html>
<head>
</head>
<body>
<my-app></my-app>
</body>
</html>
my-app.html:
<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/app-route/app-location.html">
<dom-module id="my-app">
<template>
<app-location></app-location>
<h1>Coin</h1>
</template>
<script>
class App extends Polymer.Element{
static get is(){return 'my-app'}
ready(){
super.ready()
console.log('ready')
}
}
customElements.define(App.is, App)
</script>
</dom-module>
Specifying query-params attribute to map it to a property of App does not change anything. Remove the app-location element and query string is kept.
Has anyone seen this behavior? Is there any workaround - except a rollback to a previous version?
It is a bug. You can temporarly remove the default value in iron-location element until the fix is released.
Lines to remove
value: function() {
return {};
}
Affected property
paramsObject: {
type: Object,
notify: true,
value: function() {
return {};
}
},
Reference:
https://github.com/PolymerElements/iron-location/pull/86/commits/3732e93ce2197178f76c3c2073438b9cd15096b4
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>`
Whats the difference between defining a computed property and using it like {{prop}}
prop: {
type: String,
computed: 'some(prop1)'
}
vs a function binding like
{{some(prop1)}}
The property is, as the name implies, also a property of the node object. It can notify outside listeners or reflect to attribute.
Function binding is only used to that. You can call it from the outside but it should have no effect - assuming that the function has no side-effects which is shouldn't.
The most important difference however, is that compute function will evaluate for each binding usage. Computed property will evaluate only once when a dependency changes. See below what happens in the console whenever you click INCREMENT.
Polymer({
is: 'my-elem',
properties: {
i: {
type: Number,
value: 0
},
c: {
computed: 'compute(i)'
}
},
inc: function() {
console.clear();
this.i += 1;
},
compute: function(i) {
console.log('computing property binding');
return i * 2;
},
f: function(i) {
console.log('computing function binding');
return i * 2;
}
});
<!DOCTYPE html>
<html>
<head>
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import"/>
<link href="paper-button/paper-button.html" rel="import" />
</head>
<body>
<my-elem></my-elem>
<dom-module id="my-elem">
<template>
<div>Computed: [[c]]</div>
<div>Computed: [[c]]</div>
<div>Computed: [[c]]</div>
<div>Computed: [[c]]</div>
<div>Function: [[f(i)]]</div>
<div>Function: [[f(i)]]</div>
<div>Function: [[f(i)]]</div>
<div>Function: [[f(i)]]</div>
<paper-button on-tap="inc">Increment</paper-button>
</template>
</dom-module>
</body>
</html>
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
A Polymer noob...
I'm trying to create a custom element as per the Polymer API docs, where my main page looks like this:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Polymer</title>
<script src="bower_components/platform/platform.js"></script>
<link rel="import" href="bower_components/polymer/polymer.html">
</head>
<body>
<div id="test"></div>
<polymer-element name="book-template" constructor="BookTemplate" noscript>
<template>
<style>
h1 { color: orange; }
</style>
<h1>Hello from some-foo</h1>
</template>
</polymer-element>
</body>
</html>
I know that the page content will render if I just put <book-template></book-template> on the page, or if I do something like this inside the <body> tag:
<script>
var book = document.createElement('book-template');
document.getElementById('test').appendChild(book);
</script>
But I'm trying to utilize the element's constructor attribute, assuming that this will create the element when placed somewhere inside of <body>:
<script>
var book = new BookTemplate();
</script>
...but getting a console message that BookTemplate() is not defined.
I'm sure it's something simple...any idea? Thanks in advance.
I guess you have to wait for the polymer-ready event, so that the constructor is available in the global window object http://jsbin.com/kosuf/2/edit?html,console,output:
<script>
document.addEventListener('polymer-ready',function() {
var book = new BookTemplate();
if (book) {
console.log('Ok');
}
});
</script>