RestApi call through iron-ajax of polymer - ajax

I am developing a polymer app and I want to make a call to the RestApi.
this is the how the request body is
{
"languageId": Presently English is the only supported language. Always 1,
"productCode":"Medicus",
"timeZoneName":"Time zone name of device. For e.g. Asia/Calcutta",
"timeZoneOffset": Time zone offset from UTC in milliseconds. For e.g. IST = 19800000,
"user":{
"firstName":"First name of the user",
"lastName":"Last name of the user",
"middleName":"Middle name of the user",
"password":"Password provided by the user",
"userTypeId":2 = Doctor, 3 = User,
"fields":[
{
"Id":1,
"values":["Mobile number provided by the user”]
}
]
}
}
i am not getting the proper idea of how i should specify these parameters in the params='{}' of iron-ajax element.

Put something like this in your template (I am assuming POST to your rest API, since you said body in your question. If its GET replace body= with params=
<iron-ajax
id="fetchday"
url="/api/fetchday"
handle-as="json"
content-type="application/json"
method="POST"
body="[[params]]"
last-response="{{results}}"
on-response="_gotData"
on-error="_error"></iron-ajax>
And in your polymer element properties
Polymer({
is: 'my-element'
properties: {
params: {
type: Object
}
},
_someFunction: function() {
this.params = //ASSIGN YOUR JSON OBJECT TO PARAMS HERE
this.$.fetchday.generateRequest();
},
_gotData: function(e) {
//response data is in both this.results and e.detail.response
},
_error: function() {
}
});

Related

How to Write a Composable AJAX Call in Polymer

I am trying to write a component that exposes the data from an AJAX call in Polymer. I would like to end with something like.
<get-db data={{data}}></get-db>
<template is="dom-repeat" items="{{data}}">
<div>{{item}}</div>
</template>
However, when I expose the data property from get-db component in another element, the data doesn't bind to the dom-repeat template.
The get-db component parts are as follows
<iron-ajax id="ajax"
url="https://api/endpoint"
method="post"
handle-as="json"
content-type="application/json"
body="[[request]]"
last-response="{{response}}"></iron-ajax>
...
static get properties() {
return {
response: Object,
request: Object,
username: String,
data: Object
}
}
getResponse() {
if (this.username && this.apiKey) {
this.request = {
"body": "bodyText"
};
let request = this.$.ajax.generateRequest();
request.completes.then(req => {
this.setResponse();
})
.catch(rejected => {
console.log(rejected.request);
console.log(rejected.error);
})
}
}
setResponse() {
if(this.response[0]) {
this.data = this.response[0];
}
}
The data property needs to be set to notify.
data: {
type: Object,
notify: true
}
You need to add notify but also you need to use this.set method in order to get observable changes for data properties. Also you are setting only one item to data properties (assuming you have a array at response properties.) I guess you need all array instead only 0. index as you are looping in dom-repeat. That's why this below code may help:
static get properties() {
return {
response:{
type:Object,
observer:'checkResponce'},
request: Object,
username: String,
data: {
type:Array,
notify:true}
}
}
static get observers() { return [ 'checkUserNApi(username,apiKey)']}
checkUserNApi(u,a){
if (u && a) this.$.ajax.generateRequest();
}
checkResponce(d) {
if (d) {
this.set('data',d); //with this method data property at parent will change upon you received responce
}
}
Finally, you may add to iron-ajax a line check error on-error="{{error}}" if you want to see an error report.
DEMO

Axios + Vue + Vuex manipulating a basic GET with deeply nested data

I am trying to make a basic GET call to an API using JSON API specifications with deeply nested relationship data. I'm experiencing an issue with axios or vue manipulating my data...
Paying attention to pickup and delivery relationships, the raw data looks like the following:
{
"data": {
"type": "parent",
"id": "34",
"attributes": {
// ...
},
"relationships": {
"r1": {
"data": [
{
"type": "nextparent",
"id": "62",
"attributes": {
// ..
},
"relationships": {
"pickup": {
"data": [
{
"type": "package",
"id": 521,
"attributes": {
// ...
}
},
// ...
]
},
"delivery": {
"data": []
}
}
},
// ...
]
}
}
}
}
... where pickup has an array of objects and delivery has an empty array. However, when I try to retrieve the response in the callback, delivery is an exact copy of pickup.
var promise = window.axios({
url: window.baseApi + '/my-object/34',
method: 'get'
})
promise.then(function (response) {
console.log(response)
})
Whenever you run console.log(response) in the callback, Vue's observers are applied to the response object, which makes me wonder if this is a Vue issue considering that only the relationships of the first r1 object experience this.
Screenshot of log from callback (incorrect):
Additionally, I checked the response from the axios transformResponse function and the raw json was correct (without observers). This is only happening in the callback.
Screenshot of log from transformResponse (correct):
Will update with fiddle, as soon as I can.
EDIT:
The axios function is being called in a vuex action. Here is the code:
fetchData ({commit, dispatch}) {
var promise = window.axios({
url: window.baseApi + '/my-object/34',
method: 'get'
})
promise
.then(function (response) {
console.log(response)
commit('toggleProgress', {key: 'fetchingData'})
commit('setActive', response.data.data)
dispatch('otherModule/setActiveShipments', response.data.data, {root: true})
dispatch('history/clear')
})
.catch(function () {
//
})
return promise
},

Strapi framework: can't get my page rendered

I'm starting to play with Strapi framework and tried to use Handlebars and routes to show a page. I followed the docs and I created a controller with this:
find: function *() {
try {
yield this.render('user', {
firstname: 'John',
lastname: 'Doe'
});
} catch (error) {
this.body = error;
}
},
and a router file with this:
{
"routes": {
"GET /": {
"controller": "strap",
"action": "find"
}
}
}
It is working (no errors) but I get a 404 not found status and not my page that is in views/user.html as in the docs.
What am I missing?
Interesting... Your controller and route look good.
Make sure your config looks like this:
{
"views": {
"map": {
"html": "handlebars"
},
"default": "html"
}
}
You don't need to specify the file extension in your controller only if you have a default mapping key in your config. Otherwise you need to specify the extension like this:
find: function *() {
try {
yield this.render('user.html', {
firstname: 'John',
lastname: 'Doe'
});
} catch (error) {
this.body = error;
}
},
In your HTML file:
<html>
<body>
<p>Firstname: {{ firstname }}<br>Lastname: {{ lastname }}</p>
</body>
</html>
Oh it might be a conflict between your API routes and your public assets. Can you try to remove the ./public/index.html file?

Vue.js Retrieving Remote Data for Options in Select2

I'm working on a project that is using Vue.js and Vue Router as the frontend javascript framework that will need to use a select box of users many places throughout the app. I would like to use select2 for the select box. To try to make my code the cleanest I can, I've implemented a custom filter to format the data the way select2 will accept it, and then I've implemented a custom directive similar to the one found on the Vue.js website.
When the app starts up, it queries the api for the list of users and then stores the list for later use. I can then reference the users list throughout the rest of the application and from any route without querying the backend again. I can successfully retrieve the list of users, pass it through the user list filter to format it the way that select2 wants, and then create a select2 with the list of users set as the options.
But this works only if the route that has the select2 is not the first page to load with the app. For example, if I got to the Home page (without any select2 list of users) and then go to the Users page (with a select2), it works great. But if I go directly to the Users page, the select2 will not have any options. I imagine this is because as Vue is loading up, it sends a GET request back to the server for the list of users and before it gets a response back, it will continues with its async execution and creates the select2 without any options, but then once the list of users comes back from the server, Vue doesn't know how to update the select2 with the list of options.
Here is my question: How can I retrieve the options from an AJAX call (which should be made only once for the entire app, no matter how many times a user select box is shown) and then load them into the select2 even if the one goes directly to the page with the select2 on it?
Thank you in advance! If you notice anything else I should be doing, please tell me as I would like this code to use best practices.
Here is what I have so far:
Simplified app.js
var App = Vue.extend({
ready: function() {
this.fetchUsers();
},
data: function() {
return {
globals: {
users: {
data: []
},
}
};
},
methods: {
fetchUsers: function() {
this.$http.get('./api/v1/users/list', function(data, status, response) {
this.globals.users = data;
});
},
}
});
Sample response from API
{
"data": [
{
"id": 1,
"first_name": "John",
"last_name": "Smith",
"active": 1
},
{
"id": 2,
"first_name": "Emily",
"last_name": "Johnson",
"active": 1
}
]
}
User List Filter
Vue.filter('userList', function (users) {
if (users.length == 0) {
return [];
}
var userList = [
{
text : "Active Users",
children : [
// { id : 0, text : "Item One" }, // example
]
},
{
text : "Inactive Users",
children : []
}
];
$.each( users, function( key, user ) {
var option = { id : user.id, text : user.first_name + ' ' + user.last_name };
if (user.active == 1) {
userList[0].children.push(option);
}
else {
userList[1].children.push(option);
}
});
return userList;
});
Custom Select2 Directive (Similar to this)
Vue.directive('select', {
twoWay: true,
bind: function () {
},
update: function (value) {
var optionsData
// retrive the value of the options attribute
var optionsExpression = this.el.getAttribute('options')
if (optionsExpression) {
// if the value is present, evaluate the dynamic data
// using vm.$eval here so that it supports filters too
optionsData = this.vm.$eval(optionsExpression)
}
var self = this
var select2 = $(this.el)
.select2({
data: optionsData
})
.on('change', function () {
// sync the data to the vm on change.
// `self` is the directive instance
// `this` points to the <select> element
self.set(select2.val());
console.log('emitting "select2-change"');
self.vm.$emit('select2-change');
})
// sync vm data change to select2
$(this.el).val(value).trigger('change')
},
unbind: function () {
// don't forget to teardown listeners and stuff.
$(this.el).off().select2('destroy')
}
})
Sample Implementation of Select2 From Template
<select
multiple="multiple"
style="width: 100%"
v-select="criteria.user_ids"
options="globals.users.data | userList"
>
</select>
I may have found something that works alright, although I'm not sure it's the best way to go about it. Here is my updated code:
Implementation of Select2 From Template
<select
multiple="multiple"
style="width: 100%"
v-select="criteria.reporting_type_ids"
options="globals.types.data | typeList 'reporttoauthorities'"
class="select2-users"
>
</select>
Excerpt from app.js
fetchUsers: function() {
this.$http.get('./api/v1/users/list', function(data, status, response) {
this.globals.users = data;
this.$nextTick(function () {
var optionsData = this.$eval('globals.users.data | userList');
console.log('optionsData', optionsData);
$('.select2-users').select2({
data: optionsData
});
});
});
},
This way works for me, but it still kinda feels hackish. If anybody has any other advice on how to do this, I would greatly appreciate it!
Thanks but I'm working on company legacy project, due to low version of select2, I encountered this issue. And I am not sure about the v-select syntax is from vue standard or not(maybe from the vue-select libaray?). So here's my implementation based on yours. Using input tag instead of select tag, and v-model for v-select. It works like a charm, thanks again #bakerstreetsystems
<input type="text"
multiple="multiple"
style="width: 300px"
v-model="supplier_id"
options="suppliers"
id="select2-suppliers"
>
</input>
<script>
$('#app').ready(function() {
var app = new Vue({
el: "#app",
data: {
supplier_id: '<%= #supplier_id %>', // We are using server rendering(ruby on rails)
suppliers: [],
},
ready: function() {
this.fetchSuppliers();
},
methods: {
fetchSuppliers: function() {
var self = this;
$.ajax({
url: '/admin_sales/suppliers',
method: 'GET',
success: function(res) {
self.suppliers = res.data;
self.$nextTick(function () {
var optionsData = self.suppliers;
$('#select2-suppliers').select2({
placeholder: "Select a supplier",
allowClear: true,
data: optionsData,
});
});
}
});
},
},
});
})
</script>

how to display json data fetched using ajax in each tab

I have a struts 2 action class with a method which returns json data.
I have 8 tabs on my jsp. When a user clicks on a tab, I'd like to make an ajax call to this method. I would like the returned json data to be parsed and decorated with html that can be rendered in this tab.
I'm using jquery tabs to make tabs.
How can I capture the returned json data ? Can I subscribe to some event that jquery publishes ?
How can I process the returned json data ? For e.g.; json data:
{ City : {name="New York", alias="NY", imgPath="filePath/img1.jgp"} }
I would like to extract the name and bold it.
Use the imgPath to define img tag, etc
$(document).ready(function () {
var data = { "City": [{ "name": "New York1", "alias": "NY1", "imgPath": "filePath/img1.jgp" }, { "name": "New York2", "alias": "NY2", "imgPath": "filePath/img2.jgp" }, { "name": "New York3", "alias": "NY3", "imgPath": "filePath/img3.jgp" }, { "name": "New York4", "alias": "NY4", "imgPath": "filePath/img4.jgp"}] };
if (data.City.length > 0) {
$('body').prepend('<div id="tabs1"><ul></ul></div>');
$.each(data.City, function (i, entity) {
$('#tabs1 ul').append($('<li>' + entity.name + '</li>'));
$('#tabs1').append('<div id="tabs1-' + (i + 1) + '"><p>Image Path:' + entity.imgPath + '</p></div>');
});
$("#tabs1").tabs();
}
});​
for live demo see this link: http://jsfiddle.net/nanoquantumtech/ffbx5/
You can capture the returned Json data by passing the data argument to the ajax calls success callback method which will be executed on success. http://api.jquery.com/jQuery.ajax/
You can use jQuery parse.json method and pass the json string to it. http://api.jquery.com/jQuery.parseJSON/
One more thing that your example json string is not looks like valid one. You can check your json is valid or not from this link http://jsonlint.com/ by simply pasting your json data or by pasting the url.

Resources