or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

components.mdcore-grid.mdeditors.mdformatters.mdindex.mdselection.mdutilities.md

formatters.mddocs/

0

# Formatters and Display

1

2

Cell formatting functionality providing built-in formatters and infrastructure for custom cell display components.

3

4

## Capabilities

5

6

### Built-in Formatters

7

8

Pre-built formatter components for common cell display scenarios.

9

10

```javascript { .api }

11

const formatters = {

12

/** Basic cell formatter for simple value display */

13

SimpleCellFormatter: React.ComponentType<FormatterProps>;

14

/** Checkbox formatter for select-all functionality in headers */

15

SelectAll: React.ComponentType<FormatterProps>;

16

};

17

18

interface FormatterProps {

19

/** Cell value to format and display */

20

value: any;

21

/** Complete row data object */

22

row: any;

23

/** Column definition */

24

column: Column;

25

/** Row index */

26

rowIdx: number;

27

/** Whether the cell is currently selected */

28

isSelected?: boolean;

29

/** Whether row selection is enabled */

30

isRowSelected?: boolean;

31

/** Additional properties passed from column definition */

32

[key: string]: any;

33

}

34

```

35

36

### SimpleCellFormatter

37

38

Basic formatter that displays cell values as text with null/undefined handling.

39

40

```javascript { .api }

41

/**

42

* Simple cell formatter for displaying basic text values

43

* Handles null/undefined values gracefully

44

* Supports title attribute for hover tooltips

45

*/

46

const SimpleCellFormatter: React.ComponentType<FormatterProps>;

47

```

48

49

**Usage Example:**

50

51

```javascript

52

import ReactDataGrid, { formatters } from 'react-data-grid';

53

54

const columns = [

55

{ key: 'id', name: 'ID' },

56

{

57

key: 'name',

58

name: 'Name',

59

formatter: <formatters.SimpleCellFormatter />

60

},

61

{

62

key: 'description',

63

name: 'Description',

64

formatter: <formatters.SimpleCellFormatter />

65

}

66

];

67

68

<ReactDataGrid

69

columns={columns}

70

rowGetter={i => rows[i]}

71

rowsCount={rows.length}

72

minHeight={400}

73

/>

74

```

75

76

### SelectAll Formatter

77

78

Specialized formatter for rendering select-all checkboxes in header cells.

79

80

```javascript { .api }

81

/**

82

* Select-all checkbox formatter for header cells

83

* Provides master checkbox to select/deselect all rows

84

* Works with rowSelection configuration

85

*/

86

const SelectAll: React.ComponentType<FormatterProps>;

87

```

88

89

**Usage Example:**

90

91

```javascript

92

import ReactDataGrid, { formatters } from 'react-data-grid';

93

94

const columns = [

95

{

96

key: 'select',

97

name: '',

98

formatter: <formatters.SelectAll />,

99

width: 60,

100

resizable: false,

101

sortable: false,

102

frozen: true

103

},

104

{ key: 'id', name: 'ID' },

105

{ key: 'name', name: 'Name' }

106

];

107

108

const rowSelection = {

109

showCheckbox: true,

110

enableShiftSelect: true,

111

onRowsSelected: (rows) => console.log('Selected:', rows),

112

onRowsDeselected: (rows) => console.log('Deselected:', rows),

113

selectBy: {

114

indexes: selectedIndexes

115

}

116

};

117

118

<ReactDataGrid

119

columns={columns}

120

rowGetter={i => rows[i]}

121

rowsCount={rows.length}

122

minHeight={400}

123

rowSelection={rowSelection}

124

/>

125

```

126

127

### Custom Formatter Creation

128

129

Creating custom formatters for specialized cell display requirements.

130

131

```javascript { .api }

132

/**

133

* Interface for custom formatter components

134

* Receives cell data and returns JSX for display

135

*/

136

interface CustomFormatter extends React.Component<FormatterProps> {

137

render(): JSX.Element;

138

}

139

```

140

141

**Custom Formatter Examples:**

142

143

```javascript

144

import React from 'react';

145

146

// Currency formatter

147

const CurrencyFormatter = ({ value }) => {

148

const formattedValue = new Intl.NumberFormat('en-US', {

149

style: 'currency',

150

currency: 'USD'

151

}).format(value || 0);

152

153

return (

154

<div style={{ textAlign: 'right', fontWeight: 'bold' }}>

155

{formattedValue}

156

</div>

157

);

158

};

159

160

// Status badge formatter

161

const StatusFormatter = ({ value }) => {

162

const getStatusColor = (status) => {

163

switch (status) {

164

case 'active': return '#28a745';

165

case 'inactive': return '#dc3545';

166

case 'pending': return '#ffc107';

167

default: return '#6c757d';

168

}

169

};

170

171

return (

172

<span

173

style={{

174

padding: '4px 8px',

175

borderRadius: '4px',

176

backgroundColor: getStatusColor(value),

177

color: 'white',

178

fontSize: '12px',

179

fontWeight: 'bold'

180

}}

181

>

182

{value || 'unknown'}

183

</span>

184

);

185

};

186

187

// Progress bar formatter

188

const ProgressFormatter = ({ value }) => {

189

const percentage = Math.max(0, Math.min(100, value || 0));

190

191

return (

192

<div style={{ width: '100%', backgroundColor: '#e9ecef', borderRadius: '4px' }}>

193

<div

194

style={{

195

width: `${percentage}%`,

196

height: '20px',

197

backgroundColor: '#007bff',

198

borderRadius: '4px',

199

textAlign: 'center',

200

lineHeight: '20px',

201

color: 'white',

202

fontSize: '12px'

203

}}

204

>

205

{percentage}%

206

</div>

207

</div>

208

);

209

};

210

211

// Link formatter

212

const LinkFormatter = ({ value, row }) => {

213

return (

214

<a

215

href={value}

216

target="_blank"

217

rel="noopener noreferrer"

218

style={{ color: '#007bff', textDecoration: 'underline' }}

219

>

220

{row.linkText || 'View'}

221

</a>

222

);

223

};

224

225

// Image formatter

226

const ImageFormatter = ({ value }) => {

227

return value ? (

228

<img

229

src={value}

230

alt="Preview"

231

style={{

232

width: '40px',

233

height: '40px',

234

objectFit: 'cover',

235

borderRadius: '4px'

236

}}

237

/>

238

) : (

239

<div style={{

240

width: '40px',

241

height: '40px',

242

backgroundColor: '#f8f9fa',

243

border: '1px dashed #dee2e6',

244

borderRadius: '4px'

245

}} />

246

);

247

};

248

249

// Usage in columns

250

const columns = [

251

{ key: 'id', name: 'ID' },

252

{ key: 'name', name: 'Name' },

253

{

254

key: 'price',

255

name: 'Price',

256

formatter: <CurrencyFormatter />

257

},

258

{

259

key: 'status',

260

name: 'Status',

261

formatter: <StatusFormatter />

262

},

263

{

264

key: 'progress',

265

name: 'Progress',

266

formatter: <ProgressFormatter />

267

},

268

{

269

key: 'website',

270

name: 'Website',

271

formatter: <LinkFormatter />

272

},

273

{

274

key: 'avatar',

275

name: 'Avatar',

276

formatter: <ImageFormatter />,

277

width: 80

278

}

279

];

280

```

281

282

### Conditional Formatting

283

284

Using formatters with conditional logic based on cell values or row data.

285

286

```javascript

287

// Conditional cell styling formatter

288

const ConditionalFormatter = ({ value, row, column }) => {

289

const getStyle = () => {

290

if (column.key === 'amount' && value < 0) {

291

return { color: 'red', fontWeight: 'bold' };

292

}

293

if (column.key === 'status' && row.priority === 'high') {

294

return { backgroundColor: '#fff3cd', padding: '4px' };

295

}

296

return {};

297

};

298

299

return (

300

<div style={getStyle()}>

301

{value}

302

</div>

303

);

304

};

305

306

// Multi-value formatter

307

const TagsFormatter = ({ value }) => {

308

const tags = Array.isArray(value) ? value : [];

309

310

return (

311

<div style={{ display: 'flex', gap: '4px', flexWrap: 'wrap' }}>

312

{tags.map((tag, index) => (

313

<span

314

key={index}

315

style={{

316

padding: '2px 6px',

317

backgroundColor: '#e9ecef',

318

borderRadius: '12px',

319

fontSize: '11px',

320

color: '#495057'

321

}}

322

>

323

{tag}

324

</span>

325

))}

326

</div>

327

);

328

};

329

330

// Date formatter

331

const DateFormatter = ({ value }) => {

332

if (!value) return null;

333

334

const date = new Date(value);

335

const formattedDate = date.toLocaleDateString('en-US', {

336

year: 'numeric',

337

month: 'short',

338

day: 'numeric'

339

});

340

341

return (

342

<div title={date.toISOString()}>

343

{formattedDate}

344

</div>

345

);

346

};

347

```

348

349

### Formatter Configuration

350

351

Column-level configuration for cell formatting and display.

352

353

```javascript { .api }

354

interface FormattedColumn extends Column {

355

/** Custom formatter component for cell display */

356

formatter?: React.ComponentType<FormatterProps>;

357

/** Additional properties passed to formatter */

358

[key: string]: any;

359

}

360

```

361

362

### Advanced Formatting Patterns

363

364

Complex formatting scenarios with interactive elements and custom styling.

365

366

```javascript

367

// Interactive formatter with buttons

368

const ActionFormatter = ({ value, row, rowIdx }) => {

369

const handleEdit = () => {

370

console.log('Edit row:', rowIdx, row);

371

};

372

373

const handleDelete = () => {

374

console.log('Delete row:', rowIdx, row);

375

};

376

377

return (

378

<div style={{ display: 'flex', gap: '4px' }}>

379

<button

380

onClick={handleEdit}

381

style={{

382

padding: '2px 8px',

383

fontSize: '12px',

384

backgroundColor: '#007bff',

385

color: 'white',

386

border: 'none',

387

borderRadius: '4px',

388

cursor: 'pointer'

389

}}

390

>

391

Edit

392

</button>

393

<button

394

onClick={handleDelete}

395

style={{

396

padding: '2px 8px',

397

fontSize: '12px',

398

backgroundColor: '#dc3545',

399

color: 'white',

400

border: 'none',

401

borderRadius: '4px',

402

cursor: 'pointer'

403

}}

404

>

405

Delete

406

</button>

407

</div>

408

);

409

};

410

411

// Rich content formatter

412

const RichContentFormatter = ({ value, row }) => {

413

return (

414

<div style={{ padding: '4px' }}>

415

<div style={{ fontWeight: 'bold', fontSize: '14px' }}>

416

{row.title}

417

</div>

418

<div style={{ fontSize: '12px', color: '#6c757d' }}>

419

{row.subtitle}

420

</div>

421

<div style={{ fontSize: '11px', marginTop: '2px' }}>

422

{value}

423

</div>

424

</div>

425

);

426

};

427

428

// Sparkline formatter (requires chart library)

429

const SparklineFormatter = ({ value }) => {

430

const data = Array.isArray(value) ? value : [];

431

432

return (

433

<div style={{ width: '100px', height: '30px' }}>

434

{/* Would integrate with chart library like Chart.js or D3 */}

435

<svg width="100" height="30">

436

{data.map((point, index) => (

437

<circle

438

key={index}

439

cx={index * (100 / data.length)}

440

cy={30 - (point * 30)}

441

r="2"

442

fill="#007bff"

443

/>

444

))}

445

</svg>

446

</div>

447

);

448

};

449

```

450

451

### Performance Considerations

452

453

- Formatters are called for every visible cell during rendering

454

- Keep formatter logic lightweight to maintain grid performance

455

- Use React.memo for complex formatters to prevent unnecessary re-renders

456

- Avoid heavy computations or API calls within formatters

457

458

```javascript

459

import React, { memo } from 'react';

460

461

// Optimized formatter with memoization

462

const OptimizedFormatter = memo(({ value, row }) => {

463

const expensiveCalculation = useMemo(() => {

464

return complexCalculation(value);

465

}, [value]);

466

467

return (

468

<div>

469

{expensiveCalculation}

470

</div>

471

);

472

});

473

```