I am trying to work with a client's API that lets me retrieve a group of orders in json format. I am able to use the code below which will display three alert boxes. The first box shows 200 (am assuming that's the html success code), then I get a blank alert box, then the third box says: [object Object].
In Chrome if I use the F12 key and go to Network Preview I see three sections, the Status which contains a Body section which contains the Orders section. There are 50 orders in the Orders section. Each order has properties such as: order_type: "Pickup", etc. My question is how do I iterate through the actual orders. I don't know the syntax to reach the order, and the properties inside the order.
My end goal is to loop though all 50 orders, assign some of the order properties to JavaScript vars and then pass that into an MVC controller which will insert that order into my database. Basically getting orders from the Clients database via their API and storing them into my local database. I am guessing that I will be using a another ajax call from inside the for first .each loop to post several of the order properties into my database via a call to an MVC controller that will do the database inserts?
Thank you in advance for any help.
$.ajax({
type: 'GET',
url: 'https://api.customer.com/2000105850/orders.json?v=1&key=12345',
success: function (data) {
$.each(data, function (index, element) {
alert(element);
});
}
});
Based on the information you've provided. The first 200 alert would be the count (number_of_orders_in_response). What you're doing with $.each is iterating over the objects properties, not the orders. The orders are a property on the data object. So data.orders is the array you want.
Try this:
$.ajax({
type: 'GET',
url: 'https://api.customer.com/2000105850/orders.json?v=1&key=12345',
success: function (data) {
var orders = data.orders;
var i = orders.length;
while (i--) {
alert(orders[i].order_type);
}
}
});
Also, it looks like there is pagination involved. So you will need to take that into consideration when writing your script to ensure you capture all the pages available, not just the first.
Change the first parameter of $.each from data to data.orders
Related
I'm working with a non-profit cat shelter trying to update their website. They want to have a page that connects to their shelter manager software to display the available cats for adoption. Luckily, their shelter manager offers API calls to get the information I need from it.
They use Wix as their platform and are pretty set on keeping it as most of their volunteers know how to make easy adjustments to other pages. I researched and found Wix offers the ability to connect to the API using their fetch method.
Basically, I am trying to get a dynamic page to display a repeater that is populated from their json API Get method.
Currently, for the backend I have (URL to API removed for security):
import {fetch} from 'wix-fetch';
export function getdata(){
return fetch('URL to API Service', {method: 'get'})
.then( (httpResponse) => {
if (httpResponse.ok) {
return httpResponse.json();
}
} );
}
On the page, this is where I think I am getting stuck:
import {getdata} from 'backend/fetchCats';
getdata()
.then(json => {
console.log(json);
var catData = json;
// static repeater data
$w.onReady(function () {
// handle creation of new repeated items
$w("#repeater1").onItemReady( ($item, itemData, index) => {
$item("#text23").text = itemData.ANIMALNAME;
} );
// set the repeater data, triggering the creation of new items
$w("#repeater1").data = catData;
} );
});
The above is giving me the error: Wix code SDK error: Each item in the items array must have a member named _id which contains a unique value identifying the item.
I know the JSON call has an ID field in it, but I am guessing Wix is expecting an _id field.
Am I just doing this wrong? Or am I missing something simple? I've spent a couple nights searching but can't really find a full example online that uses Wix's fetch method to get data via my HTTPS Get.
Thanks for any help!
You are doing fine.
You are getting the error from the line $w("#repeater1").data = catData;
which is the line used to set the items into the repeater. A repeater expects to have a _id member for each of the items, and your data quite probably does not have such an attribute.
I assume the API you are using, when returning an array, each item has some identifying attribute? if so, you can just do a simple transform like -
let catDataWithId = catData.map(item => {
item._id = item.<whatever id attribute>;
return item;
});
$w("#repeater1").data = catData;
I'm creating a website where I want to perform CRUD operations to a dataset. For the sake of simplicity, assume a table of books. I understand that example.com/books should return a list of books, and example.com/books/24 should return the book with id 24.
Now, imagine that my list of books is very large, and I want to allow the user to browse the book list using a table with pagination, but as the dataset is very large I want to retrieve only the current page using AJAX.
The question is: should example.com/books return the HTML containing the table with all pagination controls and other widgets? or should it return the data in JSON format? What would be the right way to perform both calls.
Thanks in advance
In your controller you could do something like this:
function index (Request $request){
$books = Book::paginate(10);
if($request->ajax()){
//ajax request
return Response::json(view('books', compact('books'))->render());
}
//html request
return view('books', compact('books'));
}
You can pass a page parameter to the route to navigate to pages.
Example : example.com/books?page=2 will fetch the second page of results.
Suggested Approach
Render the initial request with as html like you would normaly do. Then for the next page, get the second page rendered as an ajax call and append it to the DOM.
return Response::json(view('books', compact('books'))->render());
$('.pager a').on('click', function (e) {
var page = $(this).attr('href').split('page=')[1];
e.preventDefault();
$.ajax({
type: "GET",
url: 'page=' + page,
dataType: 'json',
success:function(json){
alert("Success"+json);
},
error:function(){
alert("Error");
}
});
});
});
Take a look at Laravel Pagination
My backend is Parse.com's REST API, and parse send me back a results object that looks like:
{
...fields...
}
when there is only object, meaning any time there is a create, a read or an update to one record. When I GET a collection of objects from Parse, it sends out a results object that looks like:
{
results: [
{
...fields...
}
]
}
In ST, when I have my proxy's reader's rootProperty set to: 'results', my reader isn't able to read the record Parse sends on a create or an update and therefore the local record doesn't get synced with the one the server sent.
When I have my reader's rootProperty set to: '', my local record gets synced with the one that Parse sent, but now my list, which takes a store, isn't displaying the list of records, because Parse sends that with a "results" node.
I tried using setRootProperty, but despite confirming that the reader's root property just before calling save() on a record is in fact: '', the local record doesn't sync with Parse's response. As soon as I remove the logic that does real time changes to root property, it starts working again.
What is the suggested way of handling this situation? Any help is much appreciated! Thanks!
So you have one store with a proxy that has a certain rootProperty but you olso have 2 type of response, single object or an array of objects inside results. If it is so, definitly your proxy is able to read only one type of response.
Some solutions:
-if you can operate on server make sure you send always an array of results whether the response contains none, one or many results.
-implement a custom reader (this is what i did when i had to manage different responses and make some changes on data in the meanwhile)
Ext.define('MyApp.store.MyStore',{
extend:'Ext.data.Store',
model:'MyApp.model.MyModel',
proxy: {
type:'jsonp',
url:'#'
},
autoLoad:false,
loadSolr:function(PARAMS){
this.groupField = groupField;
Ext.data.JsonP.request({
scope:this,
url: 'http://myserver.com',
callbackKey: 'json.wrf',
params: {
PARAMS
},
success: function(response) {
// handle your response here
var records = [];
Ext.each(response.results, function(record){
records.push({
field1: record.field1,
field2: record.field2
});
});
//load your data into store
this.loadData(records);
}
});
}
});
Hope it helps, post some code if i misunderstood something
Consider a REST URL like /api/users/findByCriteria which receives POSTed JSON that contains details of the criteria, and outputs a list of Users.
How would one call this with Restangular so that its results are similar to Restangulars getList()?
Restangular.all('users').post("findByCriteria", crit)... might work, but I don't know how to have Restangular recognize that the result will be a list of Users
Restangular.all('users').getListFromPOST("findByCriteria", crit)... would be nice to be able to do, but it doesn't exist.
Doing a GET instead of a POST isn't an option, because the criteria is complex.
Well,
I experience same problem and I workaround it with plain function, which return a plain array of objects. but it will remove all Restangular helper functions. So, you cant use it.
Code snippet:
Restangular.one('client').post('list',JSON.stringify({
offset: offset,
length: length
})).then(
function(data) {
$scope.clients = data.plain();
},
function(data) {
//error handling
}
);
You can get a POST to return a properly restangularized collection by setting a custom handler for OnElemRestangularized in a config block. This handler is called after the object has been Restangularized. isCollection is passed in to show if the obect was treated as a collection or single element. In the code below, if the object is an array, but was not treated as collection, it is restangularized again, as a collection. This adds all the restangular handlers to each element in the array.
let onElemR = (changedElem, isCollection, route, Restangular: restangular.IService) => {
if (Array.isArray(changedElem) && !isCollection ) {
return Restangular.restangularizeCollection(null, changedElem, changedElem.route);
}
return changedElem;
};
RestangularProvider.setOnElemRestangularized(onElemR);
I have a very simple app that loads a JSON array using $http.get inside of a controller. It assigns the result data to scope and the HTML repeats through the results to display a list. It is a very simple angularjs example.
function ViewListCtrl($scope, $http) {
$scope.shoppinglist = [];
$scope.loadList = function () {
var httpRequest = $http({
method: 'POST',
url: 'viewList_service.asp',
data: ''
}).success(function (data, status) {
$scope.shoppinglist = data;
});
};
$scope.loadList();
}
While testing on a slow server I realized there was a 3 second blocking delay while rending the repeat region. Debugging revealed to me that my controller does not attempt to get the data until the page is loaded. My page takes 3 seconds to load. Then I must wait another 3 seconds for the json data to load.
I want to load data as soon as possible so it is ready when my controller is ready. Simply put, I want to pre-load the data so it loads in parallel to my module.
I've searched all over and the closest thing I found was "resolve", but I am not using routes. This is a very simple list and no routes or templates.
How can I load the JSON as soon as the page starts to render so it is ready when the controller is ready and there is no blocking... and then get that data into scope?
You can use the module.run method. Which is executed after the config stage is completed. To make use of this you need to create a service factory that does the actual query and caches the result
module("myapp",[]).factory('listService', function($q,$http) {
var listData;
var defer = $q.defer();
return {
loadList: function() {
if(listData) {
defer.resolve(listData);
}
else {
var httpRequest = $http({
method: 'POST',
url: 'viewList_service.asp',
data: ''
})
.success(function(data) {
listData=data;
defer.resolve(listData);
}
}
return defer.promise;
}
}
});
In your controller you still use the factory to get the data with a promise then wrapper.
listService.loadList().then(function(data) {
$scope.shoppinglist=data;
});
This way you can make the async call even before any controller related code executes.
You can load data by writing code (something like Chandermani's listService) in separate file but without using angular. you can use jquery ajax to load your data.
Then write a service in angular to read that data and pass it to your controller.
It sounds like your latency comes from a slow network + server, and not a large amount of data.
So, you could render a tag into your page, so that the data would be sent along with the page HTML response. The downside there is that you're hard-coding your data into your page. This tag would basically pre-seed the $http cache with your data.
var listJson = {...json data here, rendered server-side...};
mod.run(function($cacheFactory) {
var cache = $cacheFactory('yourListCacheId');
cache.put('list-cache-id', listJson);
// store "cache" somewhere you can retrieve it, such as a service or value.
});
Then either use the $http cache property, or wrap $http in a custom service which checks the cache.
Of course, the root of the problem is that your server takes 3 seconds per request, when you normally want that at least in the sub-second range.