A production-ready quick start that connects the Syncfusionยฎ React Pivot Table to an ASP.NET Core OData backend using a Custom Adaptor built on top of ODataV4Adaptor โ enabling remote data binding with custom request/response processing and full CRUD operations.
- ๐ Quick Overview
- โจ Key Features
- ๐ ๏ธ Prerequisites
- ๐ Project Structure
- ๐ง Understanding the Custom Adaptor
- โ๏ธ Installation & Setup
โถ๏ธ Running the Application- ๐งช Testing CRUD Operations
- ๐ง Troubleshooting
- ๐ API Reference
- ๐ค Contributing
- ๐ License & Support
- ๐ Related Resources
This project demonstrates how to bind the Syncfusionยฎ React Pivot Table to a remote ASP.NET Core OData backend using a Custom Adaptor that extends ODataV4Adaptor. A Custom Adaptor is not a standalone adaptor โ it is a thin extension class that intercepts and customizes the data flow at three well-defined points (processQuery, beforeSend, processResponse) while reusing every other feature of the underlying base adaptor.
In this sample the CustomAdaptor class:
- Rewrites the API URL to point at the ASP.NET Core OData endpoint (
http://localhost:5092/odata/Orders). - Appends a custom query parameter (
Syncfusion Grid=true) that the backend can read to identify requests originating from the Pivot Table. - Injects an
Authorizationheader on every outgoing request. - Augments each record with a client-side
SNo(serial number) field after the response is received.
| Component | Technology | Purpose |
|---|---|---|
| ๐จ Frontend | React 19 + Syncfusionยฎ EJ2 | Render the interactive Pivot Table UI |
| โ๏ธ Backend | ASP.NET Core 10.0 + OData (NewtonsoftJson) | Serve OData-formatted data, perform CRUD via OData conventions |
| ๐ Adaptor | CustomAdaptor extends ODataV4Adaptor |
Bridge between Pivot Table and OData service with custom hooks |
| ๐ Sample Data | In-memory OrdersDetails list (seeded) |
Five seeded order records used for the Pivot Table |
๐ก A Custom Adaptor is the right choice when the built-in adaptors are almost sufficient but you need to tweak a few specific behaviors โ for example adding auth headers, injecting custom query parameters, transforming responses, or attaching computed fields โ without rewriting an entire adaptor.
- ๐ Remote Data Binding โ Connects the Pivot Table to an ASP.NET Core OData endpoint over HTTP.
- ๐งฉ Custom Adaptor Pattern โ Extends
ODataV4Adaptorand overridesprocessQuery,beforeSend, andprocessResponse. - ๐ Full CRUD Support โ Insert, update (PATCH), and delete records directly from the Pivot Table drill-through grid.
- ๐๏ธ OData Query Support โ
$filter,$orderby,$top,$skip,$countare produced by the base adaptor and honored by the backend via[EnableQuery]. - ๐ก๏ธ Property Casing Preservation โ Uses
DefaultContractResolverto keep PascalCase fields likeOrderID,CustomerID. - ๐ CORS-Enabled โ Preconfigured to allow cross-origin requests from the React dev server.
- โก Drill-Through Editing โ Double-click a pivot cell to add, edit, or delete underlying records in a pop-up grid.
- ๐งฎ Client-Side Computed Fields โ
SNois added to every record on the client viaprocessResponse. - ๐ Authentication Header Injection โ Every request carries an
Authorizationheader set insidebeforeSend. - ๐ฆ Ready-to-Run โ Clone, build, and start both projects โ no database setup required (in-memory sample data).
Make sure the following software and packages are installed on your machine before running the project.
| Software / Package | Version | Purpose |
|---|---|---|
| ๐ข Node.js | 18.x or later | Runtime for the React development server |
| โ๏ธ React | 19.x | Build the Pivot Table client |
| ๐ฃ .NET SDK | 10.0 or later | Build and run the ASP.NET Core OData backend |
| ๐งโ๐ป Visual Studio / VS Code | Latest | Configure and run the backend service |
๐ฆ @syncfusion/ej2-react-pivotview |
33.1.45+ | React Pivot Table component |
๐ฆ @syncfusion/ej2-data |
33.1.45+ | DataManager, ODataV4Adaptor, and Query |
๐ฆ @syncfusion/ej2-base |
33.1.45+ | setValue helper used inside processResponse |
๐ฆ Microsoft.AspNetCore.OData |
9.4.1+ | OData endpoint support for ASP.NET Core |
๐ฆ Microsoft.AspNetCore.Mvc.NewtonsoftJson |
10.0.9+ | Preserve original property casing during JSON serialization |
custom-adaptor-with-pivot-table/
โโโ ๐ Client/ # React frontend (Pivot Table)
โ โโโ ๐ public/
โ โ โโโ index.html
โ โ โโโ manifest.json
โ โ โโโ robots.txt
โ โโโ ๐ src/
โ โ โโโ App.css # Component styles
โ โ โโโ App.js # Pivot Table + CustomAdaptor class
โ โ โโโ App.test.js
โ โ โโโ datasource.js # Local fallback sample data
โ โ โโโ index.css
โ โ โโโ index.js # React entry point
โ โ โโโ reportWebVitals.js
โ โ โโโ setupTests.js
โ โโโ package.json # React dependencies & scripts
โ
โโโ ๐ ODataV4Adaptor/ # ASP.NET Core OData backend
โ โโโ ๐ Controllers/
โ โ โโโ OrdersController.cs # OData endpoints: GET, GET(key), POST, PATCH, DELETE
โ โโโ ๐ Models/
โ โ โโโ OrdersDetails.cs # Order data model + seeded sample data
โ โโโ ๐ Properties/
โ โ โโโ launchSettings.json # Default port: 5092 (HTTP), 7181 (HTTPS)
โ โโโ appsettings.Development.json
โ โโโ appsettings.json
โ โโโ ODataV4Adaptor.csproj # Project file (net10.0)
โ โโโ ODataV4Adaptor.http # Endpoint testing file
โ โโโ Program.cs # OData + Newtonsoft.Json + CORS configuration
โ
โโโ ๐ README.md # You are here
A Custom Adaptor is a class that extends one of the built-in Syncfusionยฎ adaptors (UrlAdaptor, ODataV4Adaptor, WebApiAdaptor, GraphQLAdaptor) and overrides a small set of lifecycle methods. The base adaptor continues to handle the heavy lifting (building the request, parsing the response, applying paging, etc.), while your subclass adds the delta your application needs.
This sample extends ODataV4Adaptor and overrides three methods:
| Method | When it runs | What it does in this sample |
|---|---|---|
processQuery |
Before the HTTP request is built | Rewrites requestContext.dataSource.url to http://localhost:5092/odata/Orders and calls query.addParams('Syncfusion Grid', 'true'). |
beforeSend |
Immediately before the request is sent to the server | Sets the Authorization request header (sample value: true). |
processResponse |
After the server response is received | Iterates original.result and calls setValue('SNo', ++i, item) to attach a serial number. |
// filepath: Client/src/App.js
import * as React from 'react';
import { PivotViewComponent } from '@syncfusion/ej2-react-pivotview';
import { DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
import { setValue } from '@syncfusion/ej2-base';
import './App.css';
class CustomAdaptor extends ODataV4Adaptor {
processQuery(dm, query) {
dm.dataSource.url = 'http://localhost:5092/odata/Orders'; // Here xxxx represents the port number.
query.addParams('Syncfusion Grid', 'true'); // Add the additional parameter.
return super.processQuery.apply(this, arguments);
}
beforeSend(dm, request, settings) {
request.headers.set('Authorization', `true`);
super.beforeSend(dm, request, settings);
}
processResponse() {
let i = 0;
const original = super.processResponse.apply(this, arguments);
// Adding serial number.
if (original.result) {
original.result.forEach((item) => setValue('SNo', ++i, item));
}
return original;
}
}๐ Because the base adaptor is
ODataV4Adaptor, the request URL produced by Syncfusionยฎ uses OData v4 query syntax ($filter,$orderby,$top,$skip,$count) and the response is expected in the OData v4 shape:{ "@odata.count": N, "value": [...] }. The backend is configured to honor exactly that contract.
git clone https://github.com/SyncfusionExamples/custom-adaptor-with-pivot-table.git
cd custom-adaptor-with-pivot-tableThe backend project lives in the ODataV4Adaptor/ folder.
cd ODataV4Adaptor
dotnet restoreODataV4Adaptor.csproj references:
Microsoft.AspNetCore.ODataโ OData routing and[EnableQuery]support.Microsoft.AspNetCore.Mvc.NewtonsoftJsonโ serializes properties using their original PascalCase names (OrderID,CustomerID, etc.) instead of the default camelCase.Microsoft.AspNetCore.OpenApiโ OpenAPI metadata for development exploration.
dotnet add package Microsoft.AspNetCore.OData
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson
dotnet add package Microsoft.AspNetCore.OpenApiProgram.cs registers:
- โ
OData with
ODataConventionModelBuilderexposing theOrdersDetailsmodel under the entity set namePivotand mounted at theodataroute prefix (so the final URL is/odata/Orders). - โ
NewtonsoftJson with
DefaultContractResolverto preserve property casing. - โ
CORS with
AllowAnyOriginfor development (restrict this in production). - โ
OpenAPI mapped at
/openapiin the Development environment.
// filepath: ODataV4Adaptor/Program.cs
using Newtonsoft.Json.Serialization;
using Microsoft.OData.ModelBuilder;
using ODataV4Adaptor.Models;
using Microsoft.AspNetCore.OData;
var builder = WebApplication.CreateBuilder(args);
// Create an ODataConventionModelBuilder to build the OData model
var modelBuilder = new ODataConventionModelBuilder();
// Register the "Orders" entity set with the OData model builder
modelBuilder.EntitySet<OrdersDetails>("Orders");
// Add services to the container.
builder.Services.AddMvc().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.AllowAnyOrigin() // Allow requests from any origin.
.AllowAnyMethod() // Allow GET, POST, PUT, DELETE, etc.
.AllowAnyHeader(); // Allow any request headers.
});
});
builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();
builder.Services.AddControllers().AddOData(
options => options
.Count()
.AddRouteComponents("odata", modelBuilder.GetEdmModel()));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.UseCors();
app.Run();๐ Production CORS: Replace
AllowAnyOrigin()withpolicy.WithOrigins("https://yourdomain.com"). ๐ Default port: The HTTP launch profile inProperties/launchSettings.jsonlistens onhttp://localhost:5092. The HTTPS profile exposeshttps://localhost:7181alongsidehttp://localhost:5092. Update the URL insideClient/src/App.jsif you change this.
Models/OrdersDetails.cs defines the entity exposed through OData. It is seeded with two records (OrderID 10001 and 10002) the first time GetAllRecords() is called.
// filepath: ODataV4Adaptor/Models/OrdersDetails.cs
using System.ComponentModel.DataAnnotations;
namespace ODataV4Adaptor.Models
{
public class OrdersDetails
{
public static List<OrdersDetails> order = new List<OrdersDetails>();
public OrdersDetails()
{
}
public OrdersDetails(
int OrderID, string CustomerId, int EmployeeId, double Freight)
{
this.OrderID = OrderID;
this.CustomerID = CustomerId;
this.EmployeeID = EmployeeId;
this.Freight = Freight;
}
public static List<OrdersDetails> GetAllRecords()
{
if (order.Count() == 0)
{
int code = 10000;
for (int i = 1; i < 2; i++)
{
order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 10.0));
order.Add(new OrdersDetails(code + 2, "ANATR", i + 2, 20.0));
order.Add(new OrdersDetails(code + 3, "ANTON", i + 1, 30.0));
order.Add(new OrdersDetails(code + 4, "BLONP", i + 3, 40.0));
order.Add(new OrdersDetails(code + 5, "BOLID", i + 4, 50.0));
code += 5;
}
}
return order;
}
[Key]
public int? OrderID { get; set; }
public string? CustomerID { get; set; }
public int? EmployeeID { get; set; }
public double? Freight { get; set; }
}
}โน๏ธ The endpoint seeds five order records (
OrderID10001โ10005) the first timeGetAllRecords()is called. Each record carriesOrderID,CustomerID,EmployeeID, andFreight(adouble?rather than a string). Extend the seed loop to load additional rows.
The React client lives in the Client/ folder.
cd ../Client
npm installOpen src/App.js and confirm the url set inside processQuery matches your backend port. The sample uses the HTTP profile (http://localhost:5092).
// filepath: Client/src/App.js
import * as React from 'react';
import { PivotViewComponent } from '@syncfusion/ej2-react-pivotview';
import { DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
import { setValue } from '@syncfusion/ej2-base';
import './App.css';
class CustomAdaptor extends ODataV4Adaptor {
processQuery(dm, query) {
dm.dataSource.url = 'http://localhost:5092/odata/Orders'; // Here xxxx represents the port number.
query.addParams('Syncfusion Grid', 'true'); // Add the additional parameter.
return super.processQuery.apply(this, arguments);
}
beforeSend(dm, request, settings) {
request.headers.set('Authorization', `true`);
super.beforeSend(dm, request, settings);
}
processResponse() {
let i = 0;
const original = super.processResponse.apply(this, arguments);
// Adding serial number.
if (original.result) {
original.result.forEach((item) => setValue('SNo', ++i, item));
}
return original;
}
}
function App() {
// Configure DataManager with the CustomAdaptor.
const data = new DataManager({
url: 'http://localhost:5092/odata/Orders',
adaptor: new CustomAdaptor(),
});
const editSettings = {
allowEditing: true, // Enables the Edit button and allows users to modify existing records
allowAdding: true, // Enables the Add button and allows users to create new records
allowDeleting: true, // Enables the Delete button and allows users to remove records
mode: 'Normal' // Uses Normal mode (popup dialog) for editing; other options: 'Dialog', 'Batch'
};
const dataSourceSettings = {
dataSource: data,
expandAll: false,
rows: [{ name: 'CustomerID' }],
columns: [{ name: 'OrderID' }],
values: [{ name: 'EmployeeID' }],
formatSettings: [{ name: 'Freight', format: 'N0' }],
};
let pivotObj;
// Configure beginDrillThrough event to set the primary key for CRUD operations
function beginDrillThrough(args) {
// Iterate through all columns in the drill-through grid
for (var i = 0; i < args.gridObj.columns.length; i++) {
// Check if the current column is the primary key column
if (args.gridObj.columns[i].field === "OrderID") {
// Mark this column as the primary key
// This tells DataManager to use this column's value to uniquely identify records
args.gridObj.columns[i].isPrimaryKey = true;
} else {
// Make all other columns visible so users can view and edit them
args.gridObj.columns[i].visible = true;
// Configure the edit type for date fields to use a date picker for editing
if (args.gridObj.columns[i].field === 'OrderDate' || args.gridObj.columns[i].field === 'ShippedDate') {
args.gridObj.columns[i].editType = 'datetimepickeredit';
}
}
}
}
return (
<div className='control-section' style={{ margin: 100 }}>
<PivotViewComponent
ref={d => pivotObj = d}
id='PivotView'
height={350}
width={700}
editSettings={editSettings}
beginDrillThrough={beginDrillThrough}
dataSourceSettings={dataSourceSettings}>
</PivotViewComponent>
</div>
);
}
export default App;๐
OrderIDis marked as the primary key inside thebeginDrillThroughevent so update and delete operations know which record to target.
You need two terminals โ one for the backend OData service and one for the React client.
cd ODataV4Adaptor
dotnet runThe service will start on http://localhost:5092 (HTTP profile) by default. The HTTPS profile binds https://localhost:7181 and http://localhost:5092 if you select that profile.
Verify it works:
- ๐ Open
http://localhost:5092/odata/Ordersin your browser. - โ
You should see an OData v4 response:
{ "@odata.context": "...", "value": [ ... ] }. - ๐ข Visit
http://localhost:5092/odata/Orders?$count=trueto confirm that the inline@odata.countis returned (required for paging). - ๐ In Development you can also browse
http://localhost:5092/openapifor the generated OpenAPI document.
๐ Note the port number in the terminal output and update
dm.dataSource.urlinsideprocessQueryin Client/src/App.js if it is different from5092.
cd Client
npm startThe React app will open at http://localhost:3000 by default. ๐
You should see the Pivot Table populated with aggregated EmployeeID values, grouped by CustomerID (rows) and OrderID (columns). The serialized response also includes an SNo field on every record that you can verify in the Network tab.
- Open the browser's Developer Tools (F12) โ Network tab.
- Reload the page.
- You should see a GET request to
http://localhost:5092/odata/Orders(with$count=true) that returns status200and a JSON response containing@odata.countandvalue. - Inspect the request headers and confirm
Authorization: trueis present. - Inspect any record in the response and confirm an
SNofield was added byprocessResponse. - The Pivot Table renders the aggregated data automatically.
The Pivot Table supports full CRUD through its built-in drill-through editing grid. Because the underlying adaptor is ODataV4Adaptor, the Syncfusionยฎ DataManager issues the standard OData HTTP verbs: GET, POST, PATCH, and DELETE.
| Step | Action | Expected Network Request |
|---|---|---|
| 1๏ธโฃ | Double-click any pivot cell to open the drill-through grid showing underlying source records. | GET http://localhost:5092/odata/Orders?$count=true |
| โ 2๏ธโฃ | Click Add, fill in the new row fields, then click Update. | POST http://localhost:5092/odata/Orders |
| โ๏ธ 3๏ธโฃ | Click Edit on an existing row, change a field, then click Update. | PATCH http://localhost:5092/odata/Orders/{OrderID} |
| ๐๏ธ 4๏ธโฃ | Click Delete on a row to remove it. | DELETE http://localhost:5092/odata/Orders/{OrderID} |
| ๐ 5๏ธโฃ | The Pivot Table automatically refreshes to display the updated aggregated data from the backend. | New GET to /odata/Orders?$count=true |
๐ The
OrderIDcolumn is automatically marked as the primary key inside thebeginDrillThroughevent, so update and delete operations know which record to target. ๐งช You can also exercise the endpoints directly using the includedODataV4Adaptor.httpfile in JetBrains Rider / VS Code, or viacurl/ Postman.
| โ Issue | ๐ Symptom | โ Resolution |
|---|---|---|
| ๐ซ Empty Pivot Table | Pivot loads with no errors but no rows or values appear. | Ensure the OData response contains value (and @odata.count for paging) and that field names match dataSourceSettings (case-sensitive). |
| 404 Not Found | Network tab shows a 404 response when the Pivot Table loads. | Confirm the backend is running, the OData route is odata/Orders, and the URL in App.js matches the API port. |
| ๐ฅ 500 Internal Server Error | The Pivot Table fails and the browser shows a server error. | Check the terminal/Visual Studio output for stack traces. Common causes: null reference, missing [EnableQuery], or CORS issues. |
| ๐ CORS Blocked | Console shows Access to XMLHttpRequest ... has been blocked by CORS policy. |
Verify CORS is configured in Program.cs and app.UseCors() is called before app.MapControllers(). |
| ๐พ CRUD operations not saving | The edit dialog closes but changes are not reflected in the data. | Confirm the primary key is set in beginDrillThrough and that POST/PATCH/DELETE are mapped on OrdersController. |
| ๐ค Property casing mismatch | Pivot appears empty or shows "field not found" even though the API returns data. | Ensure DefaultContractResolver is registered in Program.cs so PascalCase fields like OrderID are preserved. Note that this sample uses Freight (double) and OrderID (int) โ there is no ShipCountry field. |
| ๐งฎ Serial numbers missing on records | SNo does not appear in the rendered data. |
Verify processResponse runs super.processResponse first and uses setValue('SNo', ++i, item) on each item. |
| ๐ Auth header not visible | The Authorization header is missing on the outgoing request. |
Confirm beforeSend calls request.headers.set('Authorization', ...) and then super.beforeSend. |
| ๐ Adaptor does nothing | Overrides have no effect. | Ensure the DataManager is constructed with new CustomAdaptor() (not new ODataV4Adaptor()) and that super.<method> is called exactly once per method. |
| ๐ SSL/TLS certificate error | Console shows net::ERR_CERT_AUTHORITY_INVALID or browser warns about an untrusted certificate. |
Run dotnet dev-certs https --clean then dotnet dev-certs https --trust (Windows/macOS). On Linux, use HTTP for local testing. |
The backend exposes the following endpoints through OrdersController (mounted under the OData route prefix odata, entity set Orders):
| Method | Route | Purpose | Request Body | Response |
|---|---|---|---|---|
GET |
/odata/Orders |
Retrieve all order records (supports $filter, $orderby, $top, $skip, $count). |
โ | OData v4 payload ({ "@odata.count": N, "value": [...] }) |
GET |
/odata/Orders/{key} |
Retrieve a single order by primary key (OrderID). |
โ | 200 OK with the matching order, or 404 Not Found |
POST |
/odata/Orders |
Insert a new order (prepended to the in-memory list). | OrdersDetails JSON |
201 Created with the inserted record |
PATCH |
/odata/Orders/{key} |
Update CustomerID, EmployeeID, and Freight of an existing order (null-coalesced). |
OrdersDetails JSON |
200 OK with the updated record, or 404 Not Found |
DELETE |
/odata/Orders/{key} |
Remove an order by primary key (OrderID). |
โ | 204 No Content, or 404 Not Found |
The OrdersDetails model exposes the following fields:
| Field | Type | Description |
|---|---|---|
OrderID |
int? |
Unique order identifier (primary key, [Key] annotated). |
CustomerID |
string? |
Identifier of the customer. |
EmployeeID |
int? |
Identifier of the handling employee. |
Freight |
double? |
Shipping cost for the order. |
โน๏ธ The current controller updates only
CustomerID,EmployeeID, andFreighton PATCH. ExtendPatchinOrdersController.csif you need to update other fields.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ
โ React Pivot Table โ โ CustomAdaptor โ โ ASP.NET Core OData โ
โ (Syncfusionยฎ EJ2) โ HTTP โ extends ODataV4Adaptor โ HTTP โ OrdersController โ
โ โ โโโโโโโบ โ - processQuery โ โโโโโโโบ โ GET /odata/Orders โ
โ drill-through CRUD โ โ โ - beforeSend โ โ POST /odata/Orders โ
โ aggregates โ render โ โโโโโโโ โ - processResponse โ โโโโโโโ โ PATCH/PUT/DELETE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโ JSON โโโโโโโโโโโโโโโโโโโโโโโโโโโโ JSON โโโโโโโโโโโโโโโโโโโโโโโโโโ
- The Pivot Table triggers a query through the
DataManager. CustomAdaptor.processQueryrewrites the URL tohttp://localhost:5092/odata/Ordersand adds theSyncfusion Grid=truequery parameter.CustomAdaptor.beforeSendinjects theAuthorizationheader.- The base
ODataV4Adaptorserializes the request as OData v4 ($filter,$top, etc.) and calls the backend. OrdersControllerhonors the query through[EnableQuery]and returns{ "@odata.count": N, "value": [...] }.CustomAdaptor.processResponsewalksoriginal.resultand adds anSNofield to each item before the Pivot Table renders it.- CRUD operations (POST / PATCH / DELETE) follow the same flow but use the verbs described in the API Reference table.
Contributions are welcome and appreciated! ๐
- ๐ด Fork the repository.
- ๐ฟ Create a feature branch:
git checkout -b feature/my-awesome-change - ๐พ Commit your changes:
git commit -m "Add my awesome change" - ๐ค Push to your branch:
git push origin feature/my-awesome-change - ๐ Open a Pull Request describing the change and its motivation.
- Follow the existing code style in both the React and ASP.NET Core projects.
- Keep changes focused โ one feature or fix per pull request.
- Update or add documentation (
README.md,custom-adaptor.md) when behavior changes. - Test your changes locally against both the backend and frontend before submitting.
This project is released under the MIT License. You are free to use, modify, and distribute the code in personal and commercial projects. See the LICENSE file for full text.
- ๐ Documentation: Syncfusionยฎ React Pivot Table Docs
- ๐ฌ Community forum: Syncfusionยฎ Community
- ๐ Bug reports & feature requests: GitHub Issues
- ๐ง Direct support: Syncfusionยฎ Support Portal (for licensed users)
- ๐ Custom Adaptor Guide: Custom Adaptor Documentation
โญ If this project helped you, please consider giving it a star on GitHub โ it helps others discover it!
- ๐ WebApiAdaptor with Pivot Table โ Companion sample using
WebApiAdaptorinstead of a Custom Adaptor. - ๐ UrlAdaptor with Pivot Table โ Companion sample using
UrlAdaptor. - ๐ PivotTable Data Binding
- ๐ DataManager Getting Started
- ๐ ODataV4Adaptor Reference
- ๐ Custom Adaptor Reference
- ๐ PivotTable Editing
- ๐ PivotTable Drill-Through