I'm using the latest Polymer (1.2.0), and I'm having trouble with databinding from iron-localstorage to the iron-ajax headers field. I'm not seeing the Authorization header set when I inspect the request. I've verified the request works when I just create a valid headers object with no databinding.
Am I doing something wrong, or is it not designed to be used like this?
<iron-localstorage name="userToken" value="{{localtoken}}" use-raw></iron-localstorage>
<iron-ajax url="api/twitter/v1/private/gettweets" last-response="{{data}}" auto
headers= '{"Authorization":"Bearer [[localtoken]]}"'
handle-as="json">
</iron-ajax>
<iron-list items="[[data.futuretweets]]" as="item">
<template>
<div>
datetime: <span>[[item.datetime]]</span>
text: <span>[[item.text]]</span>
</div>
</template>
</iron-list>
I think you have a typo error in your compound binding, here is a corrected version:
<iron-ajax url="api/twitter/v1/private/gettweets" last-response="{{data}}" auto
headers= '{"Authorization":"Bearer [[localtoken]]"}'
handle-as="json">
</iron-ajax>
[EDIT] since it is not working, try with a computed function like this:
<iron-ajax url="api/twitter/v1/private/gettweets" last-response="{{data}}" auto
headers='_computeHeaders(localtoken)'
handle-as="json">
</iron-ajax>
where
_computeHeaders(localtoken) {
return {"Authorization": "Bearer " + localtoken};
}
Shouldn't:
_computeHeaders(localtoken) {
return '{"Authorization":"Bearer ' + localtoken + '"}';
}
Instead be:
_computeHeaders: function(localtoken){
return '{"Authorization":"Bearer ' + localtoken + '"}';
}
I've found a little workaround.
I'm using loopback with authentication service enabled and I'm saving the authentication token with iron-localstorage. The problem I've found is that the "auto" of iron-ajax let start the request when any ( almost ) of the iron-ajax parameter change. When the request start the localstorage value hasn't been populated yet
<iron-localstorage name="appdata" value="{{user}}"></iron-localstorage>
and
<iron-ajax auto="{{user.id}}" headers$='{"Authorization" :"{{user.id}}"}' url="/api/data" handle-as="json" last-response="{{data}}"></iron-ajax>
the workaround is inside auto="{{user.id}}". While user isn't loaded the user.id is false. When loaded it become something that match as true. That cause also a change inside the iron-ajax header attribute and cause the "auto" request send to get fired.
Related
My iron-ajax response an object like this:
{
"id": "1",
"idcontenido": "7",
"imagenes": ["carabela.png", "DSC_9565.png"],
"tipo_imagen": "img-circle",
"html": "Esta <b>regi\u00f3n<\/b>"
}
Some ids, an array images... and one 'html' attribute.
This is my element template:
<template>
...
<p>[[ajaxResponse.html]]</p>
<iron-ajax
id="ajax"
url="..."
handle-as="json"
verbose=true
last-response={{ajaxResponse}}
loading="{{cargando}}"> </iron-ajax>
...
</template>
So I want to write the html code from server in my page, but when showing the page, the html code is not being interpretated and I can read literally:
Esta <b>regiĆ³n</b>
How can I fix this interpretated the html code?
Thanks!
Finally I have fix this with an on-response method for the iron-ajax element:
_onResponse: function (e) {
this.$.html.innerHTML = e.detail.response.html;
}
e.detail.response contains an object with a 'html' attribute, the html code I want to write in my page in a 'p' tag with id=html
I'm doing a cross origin request to fetch a json response from the url which has a Basic authentication. So on tap of the button, am setting the headers for basic authentication. When I print out the values before the request has been sent I see them. But when i check the chrome dev tool for request I don't see the headers been set. Also the request turns to be an "Options" request from "GET" request and the response comes as 401 unauthorized. Is there anything am missing?
<paper-input type="search" value="{{imageUrl}}" placeholder="Enter Image URL"></paper-input>
<div class="buttons">
<paper-button on-tap="getData" autofocus>Search</paper-button>
</div>
<iron-ajax
id="xhr"
url="https://api.com/v1"
params='{"url":"some query value"}'
handle-as="json"
method="GET"
last-response="{{ajaxResponse}}"></iron-ajax>
getData: function(){
this.$.xhr.headers['X-Requested-With'] = "XMLHttpRequest";
this.$.xhr.headers['Authorization'] = this.makeHeaders(this.user, this.password);
this.$.xhr.generateRequest();
}
By default iron-ajax does not send the credentials by default for cross-site requests
You can change this by setting the withCredentials property on the iron-ajax:
<iron-ajax
id="xhr"
url="https://api.com/v1"
params='{"url":"some query value"}'
handle-as="json"
with-credentials="true"
method="GET"
last-response="{{ajaxResponse}}"></iron-ajax>
or
this.$.xhr.withCredentials = true;
I use Polymer Starter Kit 1.0.3.
My application have different types of pages. Some of them should render data received from request to backend API.
But when the application starts, all requests from all pages immediately start.
The question is how to do the right job with the backend?
I had the same problem as you, the solution I found was to use methods in my elements to call a function that it request information to the backend when I really need it. Sorry for my English.
There is iron-ajax,this is the mainly element polymer work with backend.
Here is an example in my project
<iron-ajax auto
verbose="true"
url="[[apiCategories]]"
handle-as="json"
on-response="_onCategoriesLoadComplete"></iron-ajax>
<iron-ajax auto
id="ajaxWeapons"
verbose="true"
url="[[apiWeapons]]"
params="[[apiWeaponsParams]]"
debounce-duration="300"
handle-as="json"
last-response="{{page}}"></iron-ajax>
<iron-ajax auto
verbose="true"
url="{{apiCountries}}"
handle-as="json"
last-response="{{countries}}"></iron-ajax>
This is very useful, when param change or id change, the whole page's data will reload, the simplest way to work with backend.
Maybe you don't want to auto request, example in my code
<iron-ajax id="ajaxUserRegister"
verbose="true"
url="{{apiUsers}}"
method="PUT"
on-response="_onUserRegisterComplete"
content-type="application/json"
handle-as="json"></iron-ajax>
<iron-ajax id="ajaxUserLogin"
verbose="true"
url="{{apiUsers}}"
method="POST"
on-response="_onUserLoginComplete"
content-type="application/json"
handle-as="json"></iron-ajax>
<iron-ajax id="ajaxUserGet"
verbose="true"
url="{{apiUsers}}"
method="GET"
headers="[[user.headers]]"
on-response="_onUserGetComplete"
content-type="application/json"
handle-as="json"></iron-ajax>
You can also use backend source when you needed
com._userLogin = function () {
var {inputAccount:account,inputPassword:pwd} = this;
if (!(account && account.length >= 4)) {
this.showToast('Wrong account');
return
}
if (!(pwd && pwd.length >= 4)) {
this.showToast('Wrong password');
return
}
this.$.ajaxUserLogin.body = {name: account, password: pwd};
this.$.ajaxUserLogin.generateRequest();
};
com._onUserLoginComplete = function (e, ajax) {
if (ajax.response.error) {
this.showToast('Login faield:' + ajax.response.error);
return
}
this.user = ajax.response;
};
In conclusion,define you backend resource as a iron-ajax, this is how polymer work with backend.
I'm Using iron-ajax with iron-list and for the iron-image i need to concatenate text to the image source that has{{item.path}}
i tried this way
<iron-image style="width:80px; height:80px;" sizing="cover" src="http://mydomain/{{item.path}}.jpg" preload></iron-image>
But i get no image loaded and upon inspecting a list item it doesn't insert the path of the image coming from json data.
src="http://mydomain/{{item.path}}.jpg"
What is the way to concatenate the above
by itself src="{{item.path}}" i see the path when i inspect an item
Thanks
String interpolation is not yet supported in Polymer 1.0. You will need to use a computed binding.
For instance:
<dom-module id="your-tag">
<template>
<iron-image
style="width:80px; height:80px;"
sizing="cover"
src$="{{_getImagePath(item.path)}}"
preload></iron-image>
</template>
<script>
Polymer({
is: "your-tag",
_getImagePath: function(url) {
return 'http://mydomain/' + url + '.jpg';
}
});
</script>
</dom-module>
I have answered a similar question here.
i think you forgot to declare item.path
you should
Polymer({ item.path: "/set/your/path"});
i think this example may solve you problem:
function(myPath) {
return 'http://mydomain/' + myPath + ".jpg";
}
then you can use in the following way:
src="http://mydomain/{{myPath(item.path)}}"
you may also look here for further investigation and more comprehensive examples.
I've a custom element which, among other things, has a core-input and a paper button in it.
When the element is created, the input is disabled, and I want to enable it when I tap the button.
I've tried several ways and can't access the input's attribute.
<paper-input-decorator label="Nombre de usuario" floatingLabel>
<input id="usernameinput" value="{{UserName}}" is="core-input" disabled />
</paper-input-decorator>
<paper-button raised id="edprobutton" on-tap="{{edbutTapped}}">EDITAR</paper-button>
What should I write in
edbutTapped: function () {
},
EDIT
So, I've learned that the problem was that my username input element was inside a repeat template, and that's bad for what I was trying to do. Now I'm trying to bind a single json object to my element, with no luck so far.
What I have right now:
In my Index page:
<profile-page id="profpage" isProfile="true" entity="{{profEntity}}"></profile-page>
<script>
$(document).ready(function () {
var maintemplate = document.querySelector('#fulltemplate');
$.getJSON('api/userProfile.json', function (data) {
var jsonString = JSON.stringify(data);
alert(jsonString);
maintemplate.profEntity = jsonString;
});
}
</script>
In my element's page:
<polymer-element name="profile-page" attributes="isprofile entity">
<template>
<style>
[...]
</style>
<div flex vertical layout>
<core-label class="namepro">{{entity.Name}}</core-label>
<core-label class="subpro">{{entity.CompanyPosition}}</core-label>
<core-label class="subpro">{{entity.OrgUnitName}}</core-label>
</div>
</template>
</polymer-element>
And my JSON looks like this:
{"Name": "Sara Alvarez","CompanyPosition": "Desarrollo","OrgUnitName": "N-Adviser"}
I'm asuming I need to "update" my element somehow after changing its entity attribute?
Try the following
<script>
Polymer({
edbutTapped: function () {
this.$.usernameinput.disabled = false;
}
});
</script>
The this.$ allows you to access controls defined in an elements and the usernameinput is the id you assigned to the input.
This can go below the closing tag of the element you are defining.
'disabled' is conditional-attribute.
So this will be the correct use of it:
<input id="usernameinput" value="{{UserName}}" is="core-input" disabled?="{{isDisabled}}" />
In the prototype:
//first disable the field, can be done in ready callback:
ready: function () {
this.isDisabled = 'true';
}
//set idDisabled to 'false' i.e. enable the input
edbutTapped: function () {
this.isDisabled = 'false';
},
OK this is going to be a long answer (hence why I am not entering this as an edit of my original answer). I've just done something which is functionally the same.
The first thing is this code;
$.getJSON('api/userProfile.json', function (data) {
var jsonString = JSON.stringify(data);
alert(jsonString);
maintemplate.profEntity = jsonString;
});
Polymer has a control called core-ajax - this as it's name suggests makes an ajax call. The other really nice thing is that it can be made to execute when the URL changes. This is the code from the project I've got.
<core-ajax id="ajax"
auto=true
method="POST"
url="/RoutingMapHandler.php?Command=retrieve&Id=all"
response="{{response}}"
handleas="json"
on-core-error="{{handleError}}"
on-core-response="{{handleResponse}}">
</core-ajax>
The auto is the bit which tells it to fire when the URL changes. The description of auto from the polymer documentation is as follows;
With auto set to true, the element performs a request whenever its
url, params or body properties are changed.
you don't need the on-core-response but the on-core-error might be more useful. For my code response contains the JSON returned.
So for your code - it would be something like this
<core-ajax id="ajax"
auto=true
method="POST"
url="/api/userProfile.json"
response="{{jsonString}}"
handleas="json"
on-core-error="{{handleError}}" >
</core-ajax>
Now we have the data coming into your project we need to handle this. This is done by making use of Polymer's data-binding.
Lets detour to the element you are creating. Cannot see anything wrong with the following line.
<polymer-element name="profile-page" attributes="isprofile entity">
We have an element called 'profile-page' with two properties 'isprofile' and 'entity'.
Only because my Javascript leaves a bit to be desired I would pass each property as a seperate entity making that line
<polymer-element name="profile-page" attributes="isprofile name companyposition OrgUnitName">
Then at the bottom of your element define a script tag
<script>
Polymer({
name: "",
companyposition: "",
OrgUnitName: ""
});
</script>
Now back to the calling (profile-page). The following code (from my project) has the following;
<template repeat="{{m in response.data}}">
<map-list-element mapname="{{m.mapName}}" recordid="{{m.Id}}" on-show-settings="{{showSettings}}">
</map-list-element>
</template>
Here we repeat the following each element. In your case you only have one entry and it is stored in jsonString so your template is something like this
<template repeat="{{u in jsonString}}">
<profile-page name="{{u.name}} companyposition="{{u.companyposition}}" OrgUnitName="{{u.OrgUnitName}}">
</profile-page>
</template>
Now we get to the issue you have. Return to your profie-page element. Nothing wrong with the line
on-tap="{{edbutTapped}}"
This calls a function called edbutTapped. Taking the code I gave you earlier
<script>
Polymer({
edbutTapped: function () {
this.$.usernameinput.disabled = false;
}
});
</script>
The only thing to change here is add the following code
created: function() {
this.$.usernameinput.disabled = true;
},
This is inserted after the Polymer({ line. I cannot see in your revised code where the usernameinput is defined but I am assuming you have not posted it and it is defined in the element.
And you should be working, but remember to keep your case consistent and to be honest I've not been - certain parts of Polymer are case sensitive - that catches me out all the time :)