iron-ajax with basic auth not working - ajax

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>

Related

Kendo Vue datasource for Kendo grid with Auth Header

I am trying to create a datasource for a Kendo Grid in Vue.js. I need to put auth headers so declarative syntax in the template does not fix my problem.
The link below makes it possible for an array, but I need an example with an AJAX call or a promise (an Axios one would be perfect).
Kendo UI Grid Data variable Vue.js
A much cleaner answer came from Telerik support today. It make the world a better place :)
<!DOCTYPE html>
<html>
<head>
<base href="http://demos.telerik.com/kendo-vue-ui/wrappers/dropdownlist/index">
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.3.1018/styles/kendo.common-material.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.3.1018/styles/kendo.material.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.3.1018/styles/kendo.material.mobile.min.css" />
<script src="https://kendo.cdn.telerik.com/2017.3.1018/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2017.3.1018/js/kendo.all.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.15/browser-polyfill.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/#progress/kendo-all-vue-wrapper/dist/cdn/kendo-all-vue-wrapper.min.js"></script>
</head>
<body>
<div id="example">
<div id="app" class="demo-section k-content">
<h4>Find a product</h4>
<kendo-datasource ref="datasource"
:type="'odata'"
:server-filtering="true"
:transport-read="{ url: 'https://demos.telerik.com/kendo-ui/service/Northwind.svc/Products', beforeSend: onBeforeSend }">
</kendo-datasource>
<kendo-dropdownlist ref="dropdownlist"
:data-text-field="'ProductName'"
:filter="'contains'"
:auto-bind="true"
:data-source-ref="'datasource'">
</kendo-dropdownlist>
</div>
</div>
<style>
.demo-section .k-dropdown {
width: 100%;
}
</style>
<script>
new Vue({
el: '#app',
methods: {
onBeforeSend: function(xhr) {
var token = "asd81237hdbsjkfh234uygr38fg73";
xhr.setRequestHeader('Authorization', 'Bearer ' + token)
}
}
})
</script>
</body>
</html>
Ok, so the documentation is a bit flaky, but I managed to get a custom function going in Vue, just like in the plain Kendo UI datasource. Look at this demo for reference: http://dojo.telerik.com/uXELIh
This is a mix of declarative and custom methods, so it might look a bit odd. (I've never worked with the VUE wrapper before)
Instead of the transport-read-url="uri/to/somewhere" property just define a transport-read="readData" property.
<kendo-datasource ref="datasource1"
:transport-read="readData"
:schema-model-id="'ProductID'"
:schema-model-fields="schemaModelFields"
:batch='true'
:page-size='20'>
</kendo-datasource>
Then create the readData method:
new Vue({
el: '#app',
data: {
schemaModelFields: {
/*...*/
}
},
methods:
readData: function(e) {
//this simply returns one Product with a name Chai as a dummy
//set your Auth headers here, do the request and then pass
//the data in the e.success method as a parameter
e.success({ProductName: "Chai"})
}
}
/*...*/
});
That's all there is.
However If you have an Auth header, that you need to prepend to all your ajax requests, I'd suggest you use $.ajaxSetup() (How can I add a custom HTTP header to ajax request with js or jQuery?). This will save you the hassle of implementing this for read, update, create and delete, each and every time.
$.ajaxSetup({
headers: { 'x-my-custom-header': 'some value' }
});
A bit painful but I was able to do it with Marco's help
Here is the code
<template>
<div>
<kendo-datasource ref="datasource1"
:transport-read="readData"
:batch='true'
:page-size='20'>
</kendo-datasource>
<kendo-grid :height="550"
:data-source-ref="'datasource1'"
:pageable='true'>
</kendo-grid>
</div>
</template>
<script>
export default {
name: 'grid',
computed: {
token () {
return this.$store.state.access_token
}
},
methods: {
readData: function (e) {
console.log(this.token)
var tkn= this.token
$.ajax({
url: 'http://127.0.0.1/AssetExtranet.WebAPI2/api/Vw_Hmn_Branch',
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', 'Bearer ' + tkn)
},
dataType: 'json',
success: function (data) {
e.success(data)
},
type: 'GET'
})
}
}
}
</script>
Thank Marco and Vue is perfect and super fast. It is a joy to work with Vue after that Angular 2,3,4,5... mess.

How to reset <iron-form> after dynamically loading data using <iron-ajax> in Polymer 2.x?

I want to reset my form buttons using the reset() method of the <iron-form>element.
Desired behavior
The desired behavior is that after clicking the Reset button, the two buttons that were originally unchecked to be unchecked and the two buttons that were originally checked to be checked.
Actual behavior
The actual behavior is that after clicking the Reset button, all the buttons flip to unchecked.
Demo
Here is my Plunker demo. Note that in reality I am loading data from Firebase. In the demo, I am loading it from myjson.com.
Steps to recreate the problem
Open this demo.
Notice two checked buttons and two unchecked.
Check the two unchecked buttons.
Click the Reset button.
Notice all the buttons flip to unchecked.
The desired behavior is for the two buttons that were originally unchecked to be unchecked and the two buttons that were originally checked to be checked.
Code
https://plnkr.co/edit/viXDsAVrcmSOdAYriySm?p=preview
<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<link rel="import" href="polymer/polymer-element.html">
<link rel="import" href="paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="iron-form/iron-form.html">
<link rel="import" href="iron-ajax/iron-ajax.html">
<link rel="import" href="paper-button/paper-button.html">
<dom-module id="my-demo">
<template>
<style>
paper-button, form > * {
margin-top: 40px;
font-size: 18px;
}
</style>
<iron-ajax
id="ajax"
auto
url="https://api.myjson.com/bins/1dntup"
last-response="{{item}}"
handle-as="json"
>
</iron-ajax>
<iron-form id="form">
<form>
<paper-toggle-button name="alice" checked="{{item.alice}}">Alice</paper-toggle-button>
<paper-toggle-button name="bob" checked="{{item.bob}}">Bob</paper-toggle-button>
<paper-toggle-button name="charlie" checked="{{item.charlie}}">Charlie</paper-toggle-button>
<paper-toggle-button name="dave" checked="{{item.dave}}">Dave</paper-toggle-button>
</form>
</iron-form>
<paper-button on-tap="_onTap">Reset</paper-button>
</template>
<script>
class MyDemo extends Polymer.Element {
static get is() {
return 'my-demo';
}
static get properties() {
return {
item: {
type: Object,
notify: true,
},
};
}
ready() {
super.ready();
}
_onTap() {
this.$.form.reset();
}
}
window.customElements.define(MyDemo.is, MyDemo);
</script>
</dom-module>
Edits
User #madietov of the Polymer Slack Site points out that the source code here uses a protected method called _init() to initialize the default settings. And this _init() method seems to be called before the <iron-ajax> element returns its values.
_init() sets a protected property called _defaults. If I could access either the protected method or protected property, then I could call the method or set the property after <iron-ajax> returns its initial values.
Replace
this.$.form.reset();
with
this.$.ajax.generateRequest();
Demo
https://plnkr.co/edit/4ROGJbzqk98X6FtbVSCN?p=preview
<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<link rel="import" href="polymer/polymer-element.html">
<link rel="import" href="paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="iron-form/iron-form.html">
<link rel="import" href="iron-ajax/iron-ajax.html">
<link rel="import" href="paper-button/paper-button.html">
<dom-module id="my-demo">
<template>
<style>
paper-button, form > * {
margin-top: 40px;
font-size: 18px;
}
</style>
<iron-ajax
id="ajax"
auto
url="https://api.myjson.com/bins/1dntup"
last-response="{{item}}"
handle-as="json"
>
</iron-ajax>
<iron-form id="form">
<form>
<paper-toggle-button name="alice" checked="{{item.alice}}">Alice</paper-toggle-button>
<paper-toggle-button name="bob" checked="{{item.bob}}">Bob</paper-toggle-button>
<paper-toggle-button name="charlie" checked="{{item.charlie}}">Charlie</paper-toggle-button>
<paper-toggle-button name="dave" checked="{{item.dave}}">Dave</paper-toggle-button>
</form>
</iron-form>
<paper-button on-tap="_onTap">Reset</paper-button>
</template>
<script>
class MyDemo extends Polymer.Element {
static get is() {
return 'my-demo';
}
static get properties() {
return {
item: {
type: Object,
notify: true,
},
};
}
ready() {
super.ready();
}
_onTap() {
//this.$.form.reset();
this.$.ajax.generateRequest();
}
}
window.customElements.define(MyDemo.is, MyDemo);
</script>
</dom-module>
Credit
Summary from comments.
Hat tip: #AneesHameed

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>

Binding iron-ajax data to a template

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>

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