GraphQL Binding
The Telerik UI Grid supports multiple server-side binding approaches. With the DataSource .Custom() option, you can configure the Grid to run read and CRUD operations against a GraphQL endpoint.
What is GraphQL?
GraphQL is a query language for APIs and a runtime that fulfills client requests with existing data. It describes the available data clearly and returns only the fields requested by the client.
As an alternative to REST, GraphQL lets you fetch data from multiple related sources in a single request. A GraphQL query can access properties from one resource and follow references to related resources.
Implementing the Service
First, create a running service that follows GraphQL and .NET guidelines: Creating a GraphQL Backend on .NET
For a complete service implementation, review the public Telerik sample repository: Kendo UI Demos Service - graphql
Update Startup.cs to register the GraphQL services and schema, for example:
// Product
services.AddTransient<IProductRepository, ProductRepository>();
services.AddSingleton<ProductQuery>();
services.AddSingleton<ProductMutation>();
services.AddSingleton<ProductType>();
services.AddSingleton<ProductInputType>();
services.AddSingleton<ISchema>(new ProductsSchema(new FuncServiceProvider(type => services.BuildServiceProvider().GetService(type))));
Binding the Grid
To bind the Grid to GraphQL, configure the DataSource transport, schema, and request payload handlers.
Configuring the DataSource
Define the GraphQL endpoint URLs in the DataSource .Custom() transport configuration. When you enable editing, also configure .Schema() so the Grid can map fields and parse the response.
.DataSource(dataSource => dataSource
.Custom()
.PageSize(20)
.Schema(schema =>
{
schema.Model(model =>
{
model.Id(p => p.ProductID);
model.Field(p => p.ProductID).Editable(false).From("productID");
model.Field(p => p.ProductName).From("productName");
model.Field(p => p.UnitPrice).From("unitPrice");
model.Field(p => p.UnitsInStock).From("unitsInStock");
})
.Data(d => "schemaData")
.Total(t => "schemaTotal");
})
.Transport(transport => transport
.Create(r => r
.Url("https://demos.telerik.com/service/v2/graphql/")
.ContentType("application/json")
.Type(HttpVerbs.Post)
.Data("additionalDataOnCreate")
)
.Read(r => r
.Url("https://demos.telerik.com/service/v2/graphql/")
.ContentType("application/json")
.Type(HttpVerbs.Post)
.Data("additionalDataOnRead")
)
.Update(r => r
.Url("https://demos.telerik.com/service/v2/graphql/")
.ContentType("application/json")
.Type(HttpVerbs.Post)
.Data("additionalDataOnUpdate")
)
.Destroy(r => r
.Url("https://demos.telerik.com/service/v2/graphql/")
.ContentType("application/json")
.Type(HttpVerbs.Post)
.Data("additionalDataOnDestroy")
)
.ParameterMap("parameterMap")
)
)
Handling Parameters
Use JavaScript helper functions to send GraphQL queries and map response data:
<script>
function additionalDataOnCreate(model) {
var createQuery = "mutation CreateProductMutation($product: ProductInput!){" +
"createProduct(product: $product){" +
"productID," +
"productName," +
"unitPrice," +
"unitsInStock" +
"}" +
"}";
var queryFields = getQueryFields(model);
return {
query: createQuery,
variables: { "product": queryFields }
};
}
function additionalDataOnRead() {
var readQuery = "query {" +
"products { productID, productName, unitPrice, unitsInStock }" +
"}";
return { query: readQuery };
}
function additionalDataOnUpdate(model) {
var updateQuery = "mutation UpdateProductMutation($product: ProductInput!){" +
"updateProduct(product: $product){" +
"productID," +
"productName," +
"unitPrice," +
"unitsInStock" +
"}" +
"}";
var queryFields = getQueryFields(model);
return {
query: updateQuery,
variables: { "product": queryFields }
};
}
function additionalDataOnDestroy(model) {
var destroyQuery = "mutation DeleteProductMutation($product: ProductInput!){" +
"deleteProduct(product: $product){" +
"productID," +
"productName," +
"unitPrice," +
"unitsInStock" +
"}" +
"}";
var queryFields = getQueryFields(model);
return {
query: destroyQuery,
variables: { "product": queryFields }
};
}
function parameterMap(options, operation) {
return kendo.stringify({
query: options.query,
variables: options.variables
});
}
function schemaData(response) {
var data = response.data;
if (data.products) { return data.products; }
else if (data.createProduct) { return data.createProduct; }
else if (data.updateProduct) { return data.updateProduct; }
else if (data.deleteProduct) { return data.deleteProduct; }
}
function schemaTotal(response) {
return response.data.products.length;
}
function getQueryFields(model) {
var fields = {
"productID": model.productID,
"productName": model.productName,
"unitPrice": model.unitPrice,
"unitsInStock": model.unitsInStock
};
return fields;
}
</script>