Binding iron-ajax data to a template - ajax

I've got a Polymer (1.0) app that loads a list of books from AJAX:
book-service/book-service.html:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="book-service">
<style>
</style>
<template>
<iron-ajax
auto
url="https://example.com/books.json"
handle-as="json"
on-response="booksLoaded"></iron-ajax>
</template>
<script>
Polymer({
is: 'book-service',
properties: {
books: { type: Array }
},
created: function(){
this.books = [];
},
booksLoaded: function(request){
this.books = request.detail.response
}
});
</script>
</dom-module>
components/book-list.html:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../book-service/book-service.html">
<dom-module id="book-list">
<style>
</style>
<template>
<book-service id="service" books="{{books}}"></book-service>
<div>
<div>Books:</div>
<ul>
<template is="dom-repeat" items="{{books}}">
<li>{{item.title}}</li>
</template>
</ul>
</div>
</template>
<script>
Polymer({is: 'book-list'});
</script>
</dom-module>
While I can confirm that JSON is being received by the AJAX request, nothing is changed in the DOM. Then I noticed that the note in the Polymer 1 data binding guide that mutation requires use of Polymer methods, so I tried what was shown, and the response handler became this:
booksLoaded: function(request){
this.push('books', request.detail.response);
}
But now I get an error! Uncaught TypeError: Cannot read property 'concat' of undefined
How do I actually bind the AJAX response to the template?

Use the notify attribute to propagate the property changes up for binding.
properties: {
books: { type: Array, notify: true }
},
Additionally, you could whittle off those booksLoaded and created functions with this:
<dom-module id="book-service">
<template>
<iron-ajax
auto
url="https://example.com/books.json"
handle-as="json"
last-response="{{books}}"></iron-ajax>
</template>
<script>
Polymer({
is: 'book-service',
properties: {
books: {
type: Array,
notify: true,
value: function(){return []}
}
}
});
</script>
</dom-module>

Related

paper-autocomplete validation is not working

I'm working on polymer based front-end project. I'm pretty new at this kind of stuff and I'm struggling finding info and working examples of components I need. I know there is demo showcases of those components but they don't give me what I need.
<iron-form id="formForm">
<form>
<paper-autocomplete label="Country" required error-message="This field is required"></paper-autocomplete>
</form>
</iron-form>
When I use paper-autocomplete element inside <iron-form>, and add required attribute to it, <iron-form> calls paper-autocomplete validator. But when I create my own polymer element which has only paper-autocomplete included, iron form doesn't see it when I include it inside.
There is my custom polymer element
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="../../../bower_components/paper-autocomplete/paper-autocomplete.html">
<link rel="import" href="../globals-behavior.html">
<dom-module id="autocomplete-country">
<template>
<iron-ajax id="countryFindCall"
url="{{restUri}}/classifier/country/find"
params="{{query}}"
on-response="handleResponse"
debounce-duration="300"></iron-ajax>
<paper-autocomplete label="Country" id="country-autocomplete" remote-source="true" min-length="2"
text-property="label" value-property="value" disable-show-clear="true"></paper-autocomplete>
</template>
<script>
Polymer({
is: "autocomplete-country",
behaviors: [
GlobalsBehavior
],
properties: {
item: {
notify: true
},
query: {
type: Object
},
result: {
type: Object
},
selected: {
type: Object,
value: {}
}
},
attached: function() {...},
handleResponse: function (data) {...},
onSelect: function(event) {...},
onChange: function(event) {...},
onBlur: function() {...}
});
</script>
</dom-module>
And this is how I'm including it
<iron-form id="formForm">
<form>
<autocomplete-country item="{{request.country}}" required error-message="Field is required"></autocomplete-country>
</form>
</iron-form>
Taken from the iron-form documentation:
<iron-form> is an HTML <form> element that can validate and submit any custom elements that implement Polymer.IronFormElementBehavior.
So I guess your element should implement that and you´re good to go.
Solved this problem by adding new parameter required and adding it as attribute :
<paper-autocomplete ... required$="[[required]]" ... ></paper-autocomplete>

Load data when change neon-page

I'm new in Polymer and I trying to do mobile app use Polymer and Cordova.
I use neon-animated-pages for pretty animation, and now I have some issue with iron-ajax. When I open project in browser on localhost:8080 all my pages already loaded and if I change page I want to make iron-ajax request. How can i do this?
example index.html
<dom-module id="my-app">
<template>
<style>
// some style
</style>
<app-header-layout fullbleed>
<app-header>
<app-toolbar>
<div main-title>Title</div>
<paper-input label="page" value="{{page::change}}"></paper-input>
<paper-icon-button icon="menu"></paper-icon-button>
</app-header>
<div class="content">
<neon-animated-pages id="page"
selected="{{page}}"
attrForSelected="index"
entry-animation="slide-from-right-animation"
exit-animation="slide-left-animation">
<neon-animatable index="0"><login-app name="login"></login-app></neon-animatable>
<neon-animatable index="1"><profile-page name="profile"></profile-page></neon-animatable>
<neon-animatable index="2"><secondary-page name="secondary"></secondary-page></neon-animatable>
</neon-animated-pages>
</div>
<footer>
© Polymer project
</footer>
</app-header-layout>
</template>
<script>
Polymer({
is: 'my-app',
behaviors: [GlobalsBehaviour],
properties: {
page: {
type: Number,
reflectToAttribute: true,
value: 0
}
}
});
</script>
And example some page with iron-ajax:
<dom-module id="secondary-page">
<template>
<style>
:host {
display: block;
}
</style>
<div>secondary PAGE</div>
<div>Var value - {{my}}</div>
<iron-ajax
id="login"
url="https://www.some.url/"
method="get"></iron-ajax>
</template>
<script>
Polymer({
is: 'secondary-page',
properties: {
my: {
type: String,
value: 'my'
}
}
});
</script>

iron-ajax with basic auth not working

I'm trying to make a request from my polymer frontend to my java-jersey backend using iron-ajax, but can't seem to work out a way to do basic auth without hardcoding it as an attribute. I don't know where to write the header-making method so that it gets used by the iron-ajax. I tried putting it both inside and outside Polymer({}) and still it doesn't get called. Here's my code. Please help. Thanks.
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="activity-feed">
<style is="custom-style" include="iron-flex iron-flex-alignment">
.cont{ height:90vh; overflow: auto;}
core-list .row{height: 80px;padding: 16px}
</style>
<template>
<div class="cont">
<iron-ajax
auto
url="http://localhost:8080/tip/webapi/home"
handle-as="json"
method="GET"
headers='{"Authorization": {{makeheaders(gi,tanu)}}}'
last-response="{{gogo}}"
></iron-ajax>
<div>{{gogo.id}}</div>
</div>
</template>
</dom-module>
<script>
Polymer({
is : "activity-feed",
makeheaders: function(user,pass){
console.log('ceva tot se intampla');
},
});
function makeheaders(user, pass) {
console.log('merge functia');
return "Basic " + btoa(user + ":" + pass);
}
</script>
Your iron-ajax element is set to "auto" which kicksoff the api request at startup. You could remove the auto attribute, and define an combined observer for user and pass to calculate the header, then manually send the request:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="activity-feed">
<style is="custom-style" include="iron-flex iron-flex-alignment">
.cont{ height:90vh; overflow: auto;}
core-list .row{height: 80px;padding: 16px}
</style>
<template>
<div class="cont" >
<iron-ajax
id="xhr"
url="http://localhost:8080/tip/webapi/home"
handle-as="json"
method="GET"
headers='[[headers]]'
last-response="{{gogo}}"
></iron-ajax>
<div>{{gogo.id}}</div>
</div>
</template>
</dom-module>
<script>
Polymer({
is : "activity-feed",
properties: {
headers: {
type: Object,
value: function() { return {}; }
},
user: String,
pass: String
},
makeHeaders: function(user,pass){
return "Basic " + window.btoa(user + ":" + pass);
},
observers: ['_setBasicAuth(user, pass)'],
_setBasicAuth(user, pass){
// might be needed
this.headers['X-Requested-With'] = "XMLHttpRequest";
// this sets your Auth header
this.headers['Authorization'] = this.makeHeaders(user, pass);
this.$.xhr.generateRequest();
}
});
</script>

Polymer Iron-Ajax Does not Display Data

I'm facing a problem, when i using Polymer's iron-ajax element.
I have a custom element like that:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="first-element">
<template>
<!-- Stylesheet-->
<style>
::host{
display:block;
}
</style>
<!-- Element content -->
<h1>
{{yolo}}
</h1>
<iron-ajax
auto
url="http://s3.amazonaws.com/codecademy-content/courses/ltp4/forecast-api/forecast.json"
handle-as="json"
on-response="handleResponse"
last-response="ajaxResponse"></iron-ajax>
<span>{{ajaxResponse.city_name}}</span>
</template>
<script>
Polymer({
is: "first-element",
properties: {
yolo: {
type: String,
value: 'YOLOOO'
}
},
handleResponse: function(){
console.log('Jobs Done')
}
});
</script>
</dom-module>
The handleResponse function, also display's browsers developer console, so that request is working correctly. Databinding also working correctly, i can also see my "yolo" properties value.
But, it doesn't display data, i also use brackets e.g [[ajaxResponse.city_name]]
How can I solve that? Thanks for help!
You are not binding iron-ajax last-response attribute to any of your polymer element properties, it's supposed to be : last-response = "{{ajaxResponse}}".
In addition the amazon request need to be loaded over https.
Here is Plunkr to see it in action.
You can check this PolyCast on iron-ajax if you want to learn more.
<dom-module id="first-element">
<template>
<!-- Stylesheet-->
<style>
::host {
display: block;
}
.icon{
width:35px;
height:auto;
float:right;
position:relative;
top:-20px;
}
</style>
<!-- Element content -->
<h1>
{{yolo}}
</h1>
<iron-ajax auto url="https://s3.amazonaws.com/codecademy-content/courses/ltp4/forecast-api/forecast.json" handle-as="json" on-response="handleResponse" last-response="{{ajaxResponse}}"></iron-ajax>
<h1>{{ajaxResponse.city_name}}</h1>
<template is="dom-repeat" items="{{ajaxResponse.days}}" index-as="day_no">
<div>
<hr>
<span>Day : {{day_no}}</span>
<br>
<img src="{{item.icon}}" alt="" class="icon">
<span> High: {{item.high}} C</span>
<br>
<span> Low: {{item.low}} C</span>
</div>
</template>
</template>
<script>
Polymer({
is: "first-element",
properties: {
yolo: {
type: String,
value: 'YOLOOO'
},
ajaxResponse: {
type: Array
}
},
handleResponse: function(e) {
console.log(e.detail.xhr.response);
}
});
</script>
</dom-module>

Custom Polymer component returning error: unexpected token . base.js:164

I'm prototyping a Polymer-based front end for a clean RESTful services layer. I think I've got the component-level AJAX working, but it's not painting to the Shadow DOM...instead, I'm getting an error in Chrome: Uncaught SyntaxError: Unexpected token . from base.js:164 (root.appendChild(dom)).
My code:
<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/core-ajax/core-ajax.html">
<polymer-element name="feed-posts">
<template>
<link rel="stylesheet" href="/assets/css/bootstrap.min.css">
<link rel="stylesheet" href="/assets/css/styles.css">
<core-ajax id="stream" url="https://api.myhost.com/1/streams" handleAs="json" params=" {{ streamparams }}" auto on-core-response="{{ feedLoaded }}"></core-ajax>
<template repeat="{{f in feed }}">
<div class="tile">
<div class="heroTop">
<div class="headline">Post ID is {{ f }}</div>
</div>
</div>
</template>
<script>
Polymer('#stream', {
accesstoken: document.querySelector('app-globals').accesstoken,
userid: document.querySelector('app-globals').userid,
streamparams: { "access_token": this.accesstoken, "user_id": this.userid }
});
</script>
</template>
<script>
Polymer('newsfeed-posts', {
created: function(){
this.feed = [];
},
feedLoaded: function(){
this.feed = this.$.stream.response['post_ids'];
}
});
</script>
</polymer-element>
Is this a bug with polymer, or (infinitely more likely) user error?
Your code:
Polymer('#stream', {
this.accesstoken = document.querySelector('app-globals').accesstoken;
this.userid = document.querySelector('app-globals').userid;
this.streamparams = {
"access_token": this.accesstoken,
"user_id": this.userid
};
});
should at least look like this:
Polymer('#stream', {
accesstoken: document.querySelector('app-globals').accesstoken,
userid: document.querySelector('app-globals').userid,
streamparams: {
"access_token": this.accesstoken,
"user_id": this.userid
},
});
Use a code linter and you will find those errors (Syntax Errors) before you even run your code.
But nevertheless there are more errors in your code. Go ahead and read the awesome polymer docs.

Resources