I have a REST service that returns data. with Hal+json format. How do I consume the response in my Kendo Angular grid. My angular controller looks like this, but doesn't return anything:
...
vm.mainGridOptions = {
dataSource: {
transport: {
read: {
url: 'http://localhost:8080/people',
dataType: 'jsonp'
}
},...
.
4 Answers, 1 is accepted
To be more specific:
I have a Spring data rest service that returns data in 'hal+json'format:
{
"_embedded" : {
"people" : [ {
"firstName" : "nes0",
"lastName" : "Baggins2",
"_links" : {
"self" : {
"href" : "http://localhost:8080/people/1"
},
"person" : {
"href" : "http://localhost:8080/people/1"
}
}
}, {
"firstName" : "nes0",
"lastName" : "Baggins2",
"_links" : {
"self" : {
"href" : "http://localhost:8080/people/2"
},
"person" : {
"href" : "http://localhost:8080/people/2"
}
}
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/people"
},
"profile" : {
"href" : "http://localhost:8080/profile/people"
},
"search" : {
"href" : "http://localhost:8080/people/search"
}
},
"page" : {
"size" : 20,
"totalElements" : 14,
"totalPages" : 1,
"number" : 0
}
}
I am using the Kendo AngularJS directives for my client:
function PeopleController(logger) {
var vm = this;
vm.title = 'People';
logger.info('dataSource');
vm.mainGridOptions = {
dataSource: {
type: 'application/hal+json;charset=UTF-8',
transport: {
read: {
url: 'http://localhost:8080/people',
dataType: 'jsonp' // "jsonp" is required for cross-domain requests; use "json" for same-domain requests
},
},
schema: {
parse: function (response) {
console.log("parse");
console.log(JSON.stringify(response, null, 4));
debugger;
return response.people;
}
},
// schema: {
// data: '_embedded.people'
// },
pageSize: 4,
serverPaging: true,
serverSorting: true,
serverFiltering: true,
},
height: 550,
width: '120px',
filterable: {
mode: 'row'
},
sortable: true,
pageable: true,
columns: [{
field: 'lastName',
title: 'Last Name',
width: '120px',
filterable: {
cell: {
operator: 'contains',
showOperators: true
}
}
}, {
field: 'firstName',
title: 'First Name',
width: '220px',
filterable: {
cell: {
operator: 'contains',
showOperators: true
}
}
}]
};
The dataType is jsonp since I am running the client on port 3000 and the Rest service on local port 8080.
With this configuration, I have the dreaded error: Uncaught SyntaxError: Unexpected token :
the client issues this call:
http://localhost:8080/people?callback=jQuery22403825252088780162_1467989292513&take=4&skip=0&page=1&pageSize=4&_=1467989292514
and returns:
{
"_embedded" : {
"people" : [ ]
},
"_links" : {
"first" : {
"href" : "http://localhost:8080/people?page=0&size=20"
},
"prev" : {
"href" : "http://localhost:8080/people?page=0&size=20"
},
"self" : {
"href" : "http://localhost:8080/people"
},
"last" : {
"href" : "http://localhost:8080/people?page=0&size=20"
},
"profile" : {
"href" : "http://localhost:8080/profile/people"
},
"search" : {
"href" : "http://localhost:8080/people/search"
}
},
"page" : {
"size" : 20,
"totalElements" : 14,
"totalPages" : 1,
"number" : 1
}
}
There is obviously no data returned and the parsing is wrong since it's a 'hal+json' format and I specified 'jsonp'.
So my question is:
What is the correct setup to read 'hal+json' response using Kendoui grid with Angular?
Hello cyril,
As you probably know, when remote requests are used, DataSource by default will use jQuery ajax to make those requests and expects json response. However it is possible to make the request without our Kendo UI DataSource built-in configuration, modify or extract the people data and pass it to the success callback of the transport.read operation. Please refer to the Local or Custom Transport CRUD Operations article for more information and sample code.
Regards,
Boyan Dimitrov
Telerik by Progress
I managed to get it working to a point. I solved the cross domain issue using the 'http-proxy-middleware' package in my gulp configuration.
function startBrowserSync(isDev, specRunner) {
..
var proxyParticipant = proxyMiddleware('/people', { target: 'http://localhost:8080' });
var options = {
proxy: 'localhost:' + port,
port: 3000,
middleware: [proxyParticipant],
...
so I can drop the jsonp dataType and use json instead.
I have to format the URI generateded by the Kendo grid using 'parameterMap' so it matches what the Spring Data Rest server is expecting, for example:
http://localhost:3000/people?page=0&size=4&sort=firstName%2Casc
dataSource: {
transport: {
read: {
url: '/people',
dataType: 'json'
},
parameterMap: function (data, operation) {
var output = null;
switch (operation) {
case 'read':
var values = {};
if (data.sort && data.sort.length > 0) {
var p = {};
if (!data.sort && data.sort.length < 0) {
p = data.page(1);
} else {
p = data.page
}
values["page"] = p - 1;
values["size"] = data.pageSize;
values["sort"] = data.sort[0]['field'] + ',' + data.sort[0]['dir'];
return values;
}
else {
values["page"] = data.page - 1;
values["size"] = data.pageSize;
return values;
}
The grid will work with pagination and sort. I do however have an issue with the filters.
Spring Data Rest is expecting something along the line:
http://localhost:8080/people/search/findByLastNameContains?name=John
The 'parameterMap' won't be helpful in that case. What would be the best practice in KendoUI to generate the previous URL? I don't see any easy way to reformat the url to insert'search', findByLastNameContains, etc...
Should I use the Local or Custom Transport CRUD Operations as you mentioned it? Is there any example how to handle the filters in that case?
Thanks.
Hello cyril,
My suggesiton in this case is to use the Custom CRUD operations and initiate a jQuery request to the provided url from the read function. As commented in the http://dojo.telerik.com/oTImU example e.data contains the information you need about the filtering to construct the proper url.
Regards,Boyan Dimitrov
Telerik by Progress