Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# Syncfusion Angular Grid with Socket.IO (Custom Binding) — Real-Time CRUD

A complete example demonstrating how to connect **Syncfusion Angular Grid** with **Socket.IO** for **real-time bidirectional data synchronization**. Supports server-driven paging, sorting, filtering, searching, and full CRUD with instant updates across all connected clients.

## Key Features

- **Custom Binding Pattern**: Manual control of Socket.IO events using `dataStateChange` & `dataSourceChanged`
- **Real-Time Synchronization**: Server broadcasts changes to all connected clients instantly
- **Socket.IO Event Model**: Bidirectional communication with acknowledgment callbacks
- **Advanced Grid Behavior**: Excel-style filtering, multi-column sorting, paging, searching
- **Full CRUD**: Insert, update, delete with instant broadcasting to all clients
- **Live Connection Status**: Real-time client count and connection indicators
- **In-Memory Data Store**: Fast server-side operations with Syncfusion DataManager

## Prerequisites

- **Node.js** LTS (20+) with npm/yarn/pnpm
- **Angular** 18+
- **TypeScript** 5.x+
- **Socket.IO** 4.x+
- **@syncfusion/ej2-angular-grids** Latest
- **@syncfusion/ej2-data** Latest

---

## Quick Start

### 1) Clone the repository
```bash
git clone <your-repo-url>
cd <your-project>/SocketIO_Grid
```

---

## 2) Backend (Node.js + Socket.IO + TypeScript)

Navigate to server folder and install packages:

```bash
cd server
npm install
```

**Start the Socket.IO server:**

```bash
npm start
```

Server listens on **http://localhost:5000** with Socket.IO ready for real-time connections.

---

## 3) Frontend (Angular + Syncfusion Grid + Custom Binding)

Navigate to client folder and install packages:

```bash
cd ../client
npm install
```

**Start the Angular application:**

```bash
ng serve
```

Navigate to `http://localhost:4200`.

### Grid architecture:

- **Reads**: `dataStateChange → socket.emit('readData')` → Server processes with DataManager → Returns `{ result, count }`
- **CRUD**: `dataSourceChanged → socket.emit('crudAction')` → Server mutates data → Broadcasts `dataChanged` to ALL clients
- **Real-Time Sync**: Server broadcasts trigger automatic `grid.refresh()` on all connected clients

The client uses Socket.IO emit with acknowledgment callbacks to send Grid state and receive processed data including:

- `skip`, `take` (paging)
- `sorted` (multi-column sorting)
- `where` (filter predicates with AND/OR logic)
- `search` (toolbar search across multiple fields)

---

## Project Layout

| File/Folder | Purpose |
|-------------|---------|
| `server/src/server.ts` | Socket.IO server with connection handling & event listeners |
| `server/src/types.ts` | TypeScript interfaces for type safety |
| `server/src/data.json` | Sample employee data (in-memory store) |
| `client/src/app/app.ts` | Angular component with Socket.IO integration |
| `client/src/app/app.html` | Grid template with event bindings |
| `client/src/app/app.css` | Component styles with real-time indicators |
| `client/src/styles.css` | Syncfusion Material 3 theme imports |

---

## Common Tasks

### Add
1. Toolbar → **Add**
2. Fill employee details → **Save**
Grid triggers `dataSourceChanged → socket.emit('crudAction', { action: 'insert' })`
Server broadcasts `dataChanged` → All clients refresh instantly

### Edit
1. Select row → **Edit**
2. Modify fields → **Update**
Grid triggers `socket.emit('crudAction', { action: 'update' })`
Server broadcasts → All clients see changes

### Delete
1. Select row → **Delete**
2. Confirm
Grid triggers `socket.emit('crudAction', { action: 'remove' })`
Server broadcasts → All clients refresh

### Filtering / Searching / Sorting
- Excel filter menu with complex predicates (AND/OR logic)
- Search bar queries multiple fields with OR logic
- Multi-column sorting with direction indicators
- All operations processed server-side using Syncfusion DataManager

---

## Real-Time Sync Demonstration

**Open `http://localhost:4200` in two browser tabs side-by-side:**

1. In **Tab 1**: Add a new employee record
2. In **Tab 2**: Watch the grid refresh automatically with the new record
3. Notice the **⚡ Clients synced** indicator appears on both tabs
4. **👥 User count** updates when tabs connect/disconnect

**Key Socket.IO Events:**

- `connect` → Client establishes WebSocket connection
- `readData` → Client requests data with grid state
- `crudAction` → Client performs insert/update/delete
- `dataChanged` → Server broadcasts to all clients (triggers refresh)
- `clientCount` → Server sends updated connection count
- `disconnect` → Client closes connection

---

## Troubleshooting

**Socket.IO connection issues**
- Ensure server is running on `http://localhost:5000`
- Check browser console for connection errors
- Verify CORS is properly configured in server

**Grid not refreshing on other tabs**
- Confirm `dataChanged` event listener is registered
- Check that server is broadcasting after CRUD operations
- Verify `grid.refresh()` is called in the event handler

**Initial data not loading**
- Ensure both `viewReady` and `socketReady` flags are true
- Check `loadInitialData()` is called in both `ngAfterViewInit` and socket `connect` handler
- Verify `dataStateChange` event is properly bound in template

**Excel filter not working**
- Ensure filter requests check for `filterchoicerequest`, `filterSearchBegin`, `stringfilterrequest`
- These requests should call `dataSource(result)` callback instead of setting `grid.dataSource`
- Server must return plain array for filter choices, not `{ result, count }` format

**Timeout errors**
- Default timeout is 10 seconds in `socketEmit` helper
- Increase timeout for slower networks
- Check server is responding with acknowledgment callback

---

## Architecture Overview

**Why Socket.IO?**

Socket.IO provides **persistent bidirectional communication** between server and clients:
- **Traditional REST**: Client polls server repeatedly or manually refreshes
- **Socket.IO**: Server pushes updates instantly to all connected clients

**Data Flow:**

1. **User Action** (add/edit/delete in Tab 1)
2. **Client Emits** → `socket.emit('crudAction', data, ack)`
3. **Server Processes** → Mutates in-memory data
4. **Server Broadcasts** → `io.emit('dataChanged')` to **ALL** clients
5. **All Clients Receive** → Execute `grid.refresh()`
6. **Tab 2 Updates** → Sees changes instantly without user action

**Benefits:**
- **Zero polling**: No repeated HTTP requests
- **Instant updates**: Sub-second latency across clients
- **Scalable**: WebSocket connections are lightweight
- **Collaborative**: Multiple users see same data in real-time
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"printWidth": 100,
"singleQuote": true,
"overrides": [
{
"files": "*.html",
"options": {
"parser": "angular"
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Client

This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 21.2.0.

## Development server

To start a local development server, run:

```bash
ng serve
```

Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.

## Code scaffolding

Angular CLI includes powerful code scaffolding tools. To generate a new component, run:

```bash
ng generate component component-name
```

For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:

```bash
ng generate --help
```

## Building

To build the project run:

```bash
ng build
```

This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.

## Running unit tests

To execute unit tests with the [Vitest](https://vitest.dev/) test runner, use the following command:

```bash
ng test
```

## Running end-to-end tests

For end-to-end (e2e) testing, run:

```bash
ng e2e
```

Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.

## Additional Resources

For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"cli": {
"packageManager": "npm"
},
"newProjectRoot": "projects",
"projects": {
"client": {
"projectType": "application",
"schematics": {
"@schematics/angular:class": {
"skipTests": true
},
"@schematics/angular:component": {
"skipTests": true
},
"@schematics/angular:directive": {
"skipTests": true
},
"@schematics/angular:guard": {
"skipTests": true
},
"@schematics/angular:interceptor": {
"skipTests": true
},
"@schematics/angular:pipe": {
"skipTests": true
},
"@schematics/angular:resolver": {
"skipTests": true
},
"@schematics/angular:service": {
"skipTests": true
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular/build:application",
"options": {
"browser": "src/main.ts",
"tsConfig": "tsconfig.app.json",
"assets": [
{
"glob": "**/*",
"input": "public"
}
],
"styles": [
"src/styles.css"
]
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "6MB",
"maximumError": "8MB"
},
{
"type": "anyComponentStyle",
"maximumWarning": "4kB",
"maximumError": "8kB"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular/build:dev-server",
"configurations": {
"production": {
"buildTarget": "client:build:production"
},
"development": {
"buildTarget": "client:build:development"
}
},
"defaultConfiguration": "development"
}
}
}
}
}
Loading