or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cell-editing.mdcolumn-system.mdcore-grid.mddata-management.mdevent-system.mdindex.mdnavigation-scrolling.mdplugin-system.mdselection-focus.mdtypes-interfaces.md

column-system.mddocs/

0

# Column System

1

2

RevoGrid's column system provides comprehensive configuration for defining column behavior, appearance, and functionality including grouping, pinning, templates, and type definitions.

3

4

## Column Definitions

5

6

### Basic Column Interface

7

8

```typescript { .api }

9

interface ColumnRegular extends ColumnType {

10

prop?: ColumnProp;

11

pin?: DimensionColPin;

12

name?: DataFormat;

13

sortable?: boolean;

14

size?: number;

15

minSize?: number;

16

maxSize?: number;

17

readonly?: ReadOnlyFormat;

18

order?: Order;

19

autoSize?: boolean;

20

}

21

```

22

23

**Core Column Properties** { .api }

24

```typescript

25

type ColumnProp = string | number;

26

type DataFormat = any;

27

type DimensionColPin = 'colPinStart' | 'colPinEnd';

28

type Order = 'asc' | 'desc' | undefined;

29

```

30

31

### Column Configuration

32

33

**prop** { .api }

34

```typescript

35

prop?: ColumnProp

36

```

37

Maps column to data property. Used to reference data field in row objects.

38

39

**name** { .api }

40

```typescript

41

name?: DataFormat

42

```

43

Display name shown in column header. Can be string, number, or custom content.

44

45

**size** { .api }

46

```typescript

47

size?: number

48

```

49

Column width in pixels. Overrides default column size.

50

51

**minSize** { .api }

52

```typescript

53

minSize?: number

54

```

55

Minimum column width when resizing. Cannot be less than cell padding for performance.

56

57

**maxSize** { .api }

58

```typescript

59

maxSize?: number

60

```

61

Maximum column width when resizing or auto-sizing.

62

63

**pin** { .api }

64

```typescript

65

pin?: DimensionColPin

66

```

67

Pin column to start or end of grid. Pinned columns remain visible during horizontal scrolling.

68

69

**sortable** { .api }

70

```typescript

71

sortable?: boolean

72

```

73

Enable sorting for this column. Adds sort indicators and click handlers to header.

74

75

**readonly** { .api }

76

```typescript

77

readonly?: ReadOnlyFormat

78

```

79

Make column or specific cells readonly. Can be boolean or function returning boolean.

80

81

**order** { .api }

82

```typescript

83

order?: Order

84

```

85

Current sort order for the column.

86

87

**autoSize** { .api }

88

```typescript

89

autoSize?: boolean

90

```

91

Enable auto-sizing for this specific column.

92

93

## Column Types

94

95

### Reusable Column Types

96

97

Define reusable column configurations with shared properties:

98

99

```typescript { .api }

100

interface ColumnType extends ColumnProperties {

101

readonly?: ReadOnlyFormat;

102

cellProperties?: PropertiesFunc;

103

cellTemplate?: CellTemplateFunc<VNode>;

104

cellCompare?: CellCompareFunc;

105

size?: number;

106

minSize?: number;

107

maxSize?: number;

108

editor?: string | Edition.EditorCtr;

109

}

110

```

111

112

**Column Type Registry** { .api }

113

```typescript

114

columnTypes: {[name: string]: RevoGrid.ColumnType} = {}

115

```

116

117

```typescript

118

// Define reusable column types

119

grid.columnTypes = {

120

// Numeric column type

121

numeric: {

122

cellProperties: (params) => ({

123

class: 'numeric-cell'

124

}),

125

cellTemplate: (params) => {

126

const value = Number(params.model[params.prop]);

127

return <span class="number">{value.toLocaleString()}</span>;

128

},

129

editor: 'numeric',

130

size: 100

131

},

132

133

// Currency column type

134

currency: {

135

cellTemplate: (params) => {

136

const value = Number(params.model[params.prop]);

137

return <span class="currency">${value.toFixed(2)}</span>;

138

},

139

cellProperties: (params) => ({

140

class: 'currency-cell',

141

style: { textAlign: 'right' }

142

}),

143

size: 120

144

},

145

146

// Date column type

147

date: {

148

cellTemplate: (params) => {

149

const date = new Date(params.model[params.prop]);

150

return <span class="date">{date.toLocaleDateString()}</span>;

151

},

152

editor: 'date',

153

size: 150

154

}

155

};

156

```

157

158

### Applying Column Types

159

160

Reference column types in column definitions:

161

162

```typescript

163

grid.columns = [

164

{ prop: 'id', name: 'ID', type: 'numeric' },

165

{ prop: 'price', name: 'Price', type: 'currency' },

166

{ prop: 'createdAt', name: 'Created', type: 'date' },

167

// Override type properties

168

{

169

prop: 'amount',

170

name: 'Amount',

171

type: 'currency',

172

size: 140 // Override default currency size

173

}

174

];

175

```

176

177

## Column Grouping

178

179

### Grouped Columns

180

181

Create hierarchical column headers with grouped columns:

182

183

```typescript { .api }

184

interface ColumnGrouping {

185

children: ColumnDataSchema[];

186

name: DataFormat;

187

}

188

```

189

190

**ColumnDataSchema** { .api }

191

```typescript

192

type ColumnDataSchema = ColumnGrouping | ColumnRegular;

193

```

194

195

### Creating Column Groups

196

197

```typescript

198

grid.columns = [

199

{ prop: 'id', name: 'ID', size: 80 },

200

{

201

name: 'Personal Information',

202

children: [

203

{ prop: 'firstName', name: 'First Name', size: 120 },

204

{ prop: 'lastName', name: 'Last Name', size: 120 },

205

{ prop: 'email', name: 'Email', size: 200 }

206

]

207

},

208

{

209

name: 'Address',

210

children: [

211

{ prop: 'street', name: 'Street', size: 150 },

212

{ prop: 'city', name: 'City', size: 100 },

213

{ prop: 'zipCode', name: 'ZIP', size: 80 }

214

]

215

},

216

{ prop: 'phone', name: 'Phone', size: 120 }

217

];

218

```

219

220

### Nested Groups

221

222

Create multiple levels of grouping:

223

224

```typescript

225

grid.columns = [

226

{ prop: 'product', name: 'Product' },

227

{

228

name: 'Sales Data',

229

children: [

230

{

231

name: 'Q1',

232

children: [

233

{ prop: 'q1_jan', name: 'Jan', type: 'currency' },

234

{ prop: 'q1_feb', name: 'Feb', type: 'currency' },

235

{ prop: 'q1_mar', name: 'Mar', type: 'currency' }

236

]

237

},

238

{

239

name: 'Q2',

240

children: [

241

{ prop: 'q2_apr', name: 'Apr', type: 'currency' },

242

{ prop: 'q2_may', name: 'May', type: 'currency' },

243

{ prop: 'q2_jun', name: 'Jun', type: 'currency' }

244

]

245

}

246

]

247

}

248

];

249

```

250

251

## Column Pinning

252

253

### Pin Columns to Sides

254

255

Keep important columns visible during horizontal scrolling:

256

257

```typescript

258

grid.columns = [

259

// Pinned to start

260

{ prop: 'id', name: 'ID', pin: 'colPinStart', size: 80 },

261

{ prop: 'name', name: 'Name', pin: 'colPinStart', size: 150 },

262

263

// Regular scrollable columns

264

{ prop: 'description', name: 'Description', size: 300 },

265

{ prop: 'category', name: 'Category', size: 120 },

266

{ prop: 'status', name: 'Status', size: 100 },

267

268

// Pinned to end

269

{ prop: 'total', name: 'Total', pin: 'colPinEnd', type: 'currency' },

270

{ prop: 'actions', name: 'Actions', pin: 'colPinEnd', size: 120 }

271

];

272

```

273

274

### Pin Configuration

275

276

```typescript

277

// Pin programmatically

278

const columns = await grid.getColumns();

279

columns.forEach(column => {

280

if (column.prop === 'importantColumn') {

281

column.pin = 'colPinStart';

282

}

283

});

284

await grid.updateColumns(columns);

285

```

286

287

## Column Templates

288

289

### Cell Templates

290

291

Customize cell content rendering:

292

293

```typescript { .api }

294

type CellTemplateFunc<T> = (params: ColumnDataSchemaModel) => T;

295

```

296

297

**ColumnDataSchemaModel** { .api }

298

```typescript

299

interface ColumnDataSchemaModel {

300

prop: ColumnProp;

301

model: DataType;

302

column: ColumnRegular;

303

rowIndex: number;

304

data: DataSource;

305

}

306

```

307

308

```typescript

309

// Custom cell templates

310

grid.columns = [

311

{

312

prop: 'status',

313

name: 'Status',

314

cellTemplate: (params) => {

315

const status = params.model[params.prop];

316

const statusClass = `status-${status.toLowerCase()}`;

317

return <span class={statusClass}>{status}</span>;

318

}

319

},

320

{

321

prop: 'avatar',

322

name: 'Avatar',

323

cellTemplate: (params) => {

324

const url = params.model[params.prop];

325

return <img src={url} class="avatar" alt="User avatar" />;

326

}

327

},

328

{

329

prop: 'progress',

330

name: 'Progress',

331

cellTemplate: (params) => {

332

const value = params.model[params.prop];

333

return (

334

<div class="progress-container">

335

<div

336

class="progress-bar"

337

style={{ width: `${value}%` }}

338

></div>

339

<span class="progress-text">{value}%</span>

340

</div>

341

);

342

}

343

}

344

];

345

```

346

347

### Column Header Templates

348

349

Customize column header rendering:

350

351

```typescript { .api }

352

type ColumnTemplateFunc<T> = (params: ColumnTemplateModel) => T;

353

```

354

355

```typescript

356

grid.columns = [

357

{

358

prop: 'priority',

359

name: 'Priority',

360

columnTemplate: (params) => {

361

return (

362

<div class="priority-header">

363

<span>Priority</span>

364

<button

365

class="filter-btn"

366

onClick={() => showPriorityFilter()}

367

>

368

🔽

369

</button>

370

</div>

371

);

372

}

373

},

374

{

375

prop: 'amount',

376

name: 'Amount',

377

columnTemplate: (params) => {

378

return (

379

<div class="amount-header">

380

<span>Amount</span>

381

<small>USD</small>

382

</div>

383

);

384

}

385

}

386

];

387

```

388

389

## Column Properties

390

391

### Cell Properties

392

393

Apply dynamic properties to individual cells:

394

395

```typescript { .api }

396

type PropertiesFunc = (params: ColumnDataSchemaModel) => {[key: string]: any};

397

type ColPropertiesFunc = (params: ColumnTemplateModel) => {[key: string]: any};

398

```

399

400

```typescript

401

grid.columns = [

402

{

403

prop: 'amount',

404

name: 'Amount',

405

cellProperties: (params) => {

406

const value = params.model[params.prop];

407

return {

408

class: {

409

'positive': value > 0,

410

'negative': value < 0,

411

'zero': value === 0

412

},

413

style: {

414

fontWeight: value > 1000 ? 'bold' : 'normal',

415

color: value < 0 ? 'red' : 'inherit'

416

}

417

};

418

}

419

},

420

{

421

prop: 'status',

422

name: 'Status',

423

cellProperties: (params) => {

424

const status = params.model[params.prop];

425

return {

426

class: `status-${status}`,

427

'data-status': status,

428

title: `Status: ${status}`

429

};

430

}

431

}

432

];

433

```

434

435

### Column Properties

436

437

Apply properties to entire column headers:

438

439

```typescript

440

grid.columns = [

441

{

442

prop: 'priority',

443

name: 'Priority',

444

columnProperties: (params) => {

445

return {

446

class: 'priority-column',

447

style: {

448

backgroundColor: '#f0f0f0',

449

borderLeft: '3px solid #007acc'

450

}

451

};

452

}

453

}

454

];

455

```

456

457

## Column Operations

458

459

### Updating Columns

460

461

**getColumns** { .api }

462

```typescript

463

async getColumns(): Promise<RevoGrid.ColumnRegular[]>

464

```

465

466

**updateColumns** { .api }

467

```typescript

468

async updateColumns(cols: RevoGrid.ColumnRegular[]): Promise<void>

469

```

470

471

```typescript

472

// Get current columns

473

const currentColumns = await grid.getColumns();

474

475

// Modify columns

476

const updatedColumns = currentColumns.map(column => {

477

if (column.prop === 'amount') {

478

return {

479

...column,

480

size: 150,

481

cellTemplate: customAmountTemplate

482

};

483

}

484

return column;

485

});

486

487

// Update grid with modified columns

488

await grid.updateColumns(updatedColumns);

489

```

490

491

### Column Store Access

492

493

Access column store for direct manipulation:

494

495

**getColumnStore** { .api }

496

```typescript

497

async getColumnStore(type?: RevoGrid.DimensionCols): Promise<ColumnSource>

498

```

499

500

```typescript { .api }

501

interface ColumnSource {

502

// Column access

503

getColumns(): RevoGrid.ColumnRegular[];

504

setColumns(columns: RevoGrid.ColumnRegular[]): void;

505

506

// Individual column operations

507

getColumn(index: number): RevoGrid.ColumnRegular;

508

setColumn(index: number, column: RevoGrid.ColumnRegular): void;

509

510

// Column manipulation

511

addColumns(columns: RevoGrid.ColumnRegular[], startIndex?: number): void;

512

removeColumns(startIndex: number, count: number): void;

513

514

// Column reordering

515

moveColumn(fromIndex: number, toIndex: number): void;

516

517

// Utilities

518

refresh(): void;

519

getColumnByProp(prop: ColumnProp): RevoGrid.ColumnRegular | undefined;

520

}

521

```

522

523

### Dynamic Column Management

524

525

```typescript

526

class ColumnManager {

527

private grid: HTMLRevoGridElement;

528

529

constructor(grid: HTMLRevoGridElement) {

530

this.grid = grid;

531

}

532

533

async addColumn(column: RevoGrid.ColumnRegular, index?: number) {

534

const columnStore = await this.grid.getColumnStore();

535

536

if (index !== undefined) {

537

columnStore.addColumns([column], index);

538

} else {

539

const currentColumns = columnStore.getColumns();

540

columnStore.setColumns([...currentColumns, column]);

541

}

542

}

543

544

async removeColumn(prop: RevoGrid.ColumnProp) {

545

const columnStore = await this.grid.getColumnStore();

546

const columns = columnStore.getColumns();

547

const filteredColumns = columns.filter(col => col.prop !== prop);

548

columnStore.setColumns(filteredColumns);

549

}

550

551

async moveColumn(fromProp: RevoGrid.ColumnProp, toProp: RevoGrid.ColumnProp) {

552

const columnStore = await this.grid.getColumnStore();

553

const columns = columnStore.getColumns();

554

555

const fromIndex = columns.findIndex(col => col.prop === fromProp);

556

const toIndex = columns.findIndex(col => col.prop === toProp);

557

558

if (fromIndex >= 0 && toIndex >= 0) {

559

columnStore.moveColumn(fromIndex, toIndex);

560

}

561

}

562

563

async toggleColumnVisibility(prop: RevoGrid.ColumnProp) {

564

const columns = await this.grid.getColumns();

565

const updatedColumns = columns.map(column => {

566

if (column.prop === prop) {

567

return {

568

...column,

569

size: column.size === 0 ? 100 : 0 // Hide/show via size

570

};

571

}

572

return column;

573

});

574

575

await this.grid.updateColumns(updatedColumns);

576

}

577

}

578

```

579

580

## Column Sorting

581

582

### Sort Configuration

583

584

Enable sorting for individual columns:

585

586

```typescript

587

grid.columns = [

588

{ prop: 'name', name: 'Name', sortable: true },

589

{ prop: 'age', name: 'Age', sortable: true },

590

{ prop: 'email', name: 'Email', sortable: false }

591

];

592

```

593

594

### Programmatic Sorting

595

596

**updateColumnSorting** { .api }

597

```typescript

598

async updateColumnSorting(

599

column: RevoGrid.ColumnRegular,

600

index: number,

601

order: 'asc'|'desc',

602

additive: boolean

603

): Promise<RevoGrid.ColumnRegular>

604

```

605

606

```typescript

607

// Sort by single column

608

const nameColumn = grid.columns.find(col => col.prop === 'name');

609

await grid.updateColumnSorting(nameColumn, 0, 'asc', false);

610

611

// Multi-column sort

612

const ageColumn = grid.columns.find(col => col.prop === 'age');

613

await grid.updateColumnSorting(ageColumn, 1, 'desc', true);

614

615

// Clear sorting

616

await grid.clearSorting();

617

```

618

619

### Custom Sort Comparators

620

621

Define custom sorting logic:

622

623

```typescript { .api }

624

type CellCompareFunc = (a: any, b: any) => number;

625

```

626

627

```typescript

628

grid.columnTypes = {

629

customSort: {

630

cellCompare: (a, b) => {

631

// Custom comparison logic

632

const valueA = parseFloat(a) || 0;

633

const valueB = parseFloat(b) || 0;

634

return valueA - valueB;

635

}

636

}

637

};

638

639

grid.columns = [

640

{

641

prop: 'customValue',

642

name: 'Custom Value',

643

type: 'customSort',

644

sortable: true

645

}

646

];

647

```

648

649

## Column Events

650

651

### Column-Related Events

652

653

Listen for column-specific events:

654

655

```typescript

656

// Before columns are set

657

grid.addEventListener('beforecolumnsset', (event) => {

658

const columns = event.detail;

659

console.log('About to set columns:', columns);

660

661

// Modify columns before they're applied

662

const modifiedColumns = columns.map(col => ({

663

...col,

664

size: col.size || 120 // Ensure minimum width

665

}));

666

667

// Update event detail (if supported)

668

event.detail = modifiedColumns;

669

});

670

671

// After columns are applied

672

grid.addEventListener('aftercolumnsset', (event) => {

673

const { columns, order } = event.detail;

674

console.log('Columns applied:', columns);

675

console.log('Sort order:', order);

676

});

677

678

// Column resize events

679

grid.addEventListener('aftercolumnresize', (event) => {

680

const resizedColumns = event.detail;

681

console.log('Columns resized:', resizedColumns);

682

683

// Save column widths

684

this.saveColumnWidths(resizedColumns);

685

});

686

687

// Header click events

688

grid.addEventListener('headerclick', (event) => {

689

const column = event.detail;

690

console.log('Header clicked:', column);

691

692

// Custom header click handling

693

if (column.prop === 'actions') {

694

showColumnMenu(column);

695

}

696

});

697

```

698

699

## Usage Examples

700

701

### Complete Column Configuration

702

703

```typescript

704

class AdvancedColumnSetup {

705

private grid: HTMLRevoGridElement;

706

707

constructor(grid: HTMLRevoGridElement) {

708

this.grid = grid;

709

this.setupColumns();

710

}

711

712

private setupColumns() {

713

// Define column types

714

this.grid.columnTypes = {

715

currency: {

716

cellTemplate: (params) => {

717

const value = Number(params.model[params.prop]) || 0;

718

return <span class="currency">${value.toLocaleString('en-US', {

719

minimumFractionDigits: 2,

720

maximumFractionDigits: 2

721

})}</span>;

722

},

723

cellProperties: (params) => ({

724

class: 'text-right',

725

style: { fontFamily: 'monospace' }

726

}),

727

size: 120,

728

sortable: true

729

},

730

731

status: {

732

cellTemplate: (params) => {

733

const status = params.model[params.prop];

734

return (

735

<div class={`status-badge status-${status.toLowerCase()}`}>

736

{status}

737

</div>

738

);

739

},

740

size: 100

741

},

742

743

actions: {

744

cellTemplate: (params) => (

745

<div class="action-buttons">

746

<button onClick={() => this.editRow(params.rowIndex)}>

747

Edit

748

</button>

749

<button onClick={() => this.deleteRow(params.rowIndex)}>

750

Delete

751

</button>

752

</div>

753

),

754

readonly: true,

755

size: 120

756

}

757

};

758

759

// Configure columns with grouping and pinning

760

this.grid.columns = [

761

// Pinned identification columns

762

{

763

prop: 'id',

764

name: 'ID',

765

pin: 'colPinStart',

766

size: 80,

767

readonly: true,

768

sortable: true

769

},

770

771

// Main data group

772

{

773

name: 'Customer Information',

774

children: [

775

{ prop: 'firstName', name: 'First Name', size: 120, sortable: true },

776

{ prop: 'lastName', name: 'Last Name', size: 120, sortable: true },

777

{ prop: 'email', name: 'Email', size: 200, sortable: true }

778

]

779

},

780

781

// Financial data group

782

{

783

name: 'Financial Data',

784

children: [

785

{ prop: 'balance', name: 'Balance', type: 'currency' },

786

{ prop: 'creditLimit', name: 'Credit Limit', type: 'currency' },

787

{ prop: 'totalSpent', name: 'Total Spent', type: 'currency' }

788

]

789

},

790

791

// Status and actions (pinned to end)

792

{ prop: 'status', name: 'Status', type: 'status', pin: 'colPinEnd' },

793

{ prop: 'actions', name: 'Actions', type: 'actions', pin: 'colPinEnd' }

794

];

795

}

796

797

private editRow(rowIndex: number) {

798

// Implement edit functionality

799

console.log('Editing row:', rowIndex);

800

}

801

802

private deleteRow(rowIndex: number) {

803

// Implement delete functionality

804

console.log('Deleting row:', rowIndex);

805

}

806

}

807

808

// Usage

809

const columnSetup = new AdvancedColumnSetup(grid);

810

```

811

812

The column system provides extensive flexibility for creating sophisticated data presentations with custom templates, dynamic properties, and advanced functionality like grouping and pinning.