or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-configuration.mdbasic-selection.mdcustom-rendering.mdgrouped-options.mdindex.mdsearch-filtering.mdtagging-mode.md

grouped-options.mddocs/

0

# Grouped Options

1

2

Support for hierarchical option structures with group selection capabilities and custom group rendering.

3

4

## Capabilities

5

6

### Basic Grouping

7

8

Organize options into hierarchical groups with collapsible sections.

9

10

```typescript { .api }

11

/**

12

* Basic grouping configuration props

13

*/

14

interface BasicGroupingProps {

15

/** Property name containing the group's options array */

16

groupValues?: string;

17

18

/** Property name containing the group's display label */

19

groupLabel?: string;

20

21

/** Enable selection of entire groups at once (default: false) */

22

groupSelect?: boolean;

23

}

24

```

25

26

**Usage Example:**

27

28

```vue

29

<template>

30

<VueMultiselect

31

v-model="selectedEmployees"

32

:options="departmentGroups"

33

:multiple="true"

34

:group-values="'employees'"

35

:group-label="'department'"

36

:group-select="true"

37

label="name"

38

track-by="id">

39

</VueMultiselect>

40

</template>

41

42

<script>

43

export default {

44

data() {

45

return {

46

selectedEmployees: [],

47

departmentGroups: [

48

{

49

department: 'Engineering',

50

employees: [

51

{ id: 1, name: 'John Doe', role: 'Frontend Developer' },

52

{ id: 2, name: 'Jane Smith', role: 'Backend Developer' }

53

]

54

},

55

{

56

department: 'Design',

57

employees: [

58

{ id: 3, name: 'Alice Johnson', role: 'UX Designer' },

59

{ id: 4, name: 'Bob Wilson', role: 'Visual Designer' }

60

]

61

}

62

]

63

}

64

}

65

}

66

</script>

67

```

68

69

### Group Selection

70

71

Enable selection of entire groups with a single click.

72

73

```typescript { .api }

74

/**

75

* Group selection configuration props

76

*/

77

interface GroupSelectionProps {

78

/** Enable group selection functionality */

79

groupSelect: true;

80

81

/** Label displayed for group selection action */

82

selectGroupLabel?: string;

83

84

/** Label displayed for group deselection action */

85

deselectGroupLabel?: string;

86

}

87

```

88

89

**Usage Example:**

90

91

```vue

92

<template>

93

<VueMultiselect

94

v-model="selectedPermissions"

95

:options="permissionGroups"

96

:multiple="true"

97

:group-values="'permissions'"

98

:group-label="'category'"

99

:group-select="true"

100

select-group-label="Select all permissions in this category"

101

deselect-group-label="Remove all permissions in this category"

102

label="name"

103

track-by="id">

104

</VueMultiselect>

105

</template>

106

107

<script>

108

export default {

109

data() {

110

return {

111

selectedPermissions: [],

112

permissionGroups: [

113

{

114

category: 'User Management',

115

permissions: [

116

{ id: 'user.create', name: 'Create Users' },

117

{ id: 'user.edit', name: 'Edit Users' },

118

{ id: 'user.delete', name: 'Delete Users' }

119

]

120

},

121

{

122

category: 'Content Management',

123

permissions: [

124

{ id: 'content.create', name: 'Create Content' },

125

{ id: 'content.publish', name: 'Publish Content' }

126

]

127

}

128

]

129

}

130

}

131

}

132

</script>

133

```

134

135

### Group State Management

136

137

Methods for managing group selection state.

138

139

```typescript { .api }

140

/**

141

* Group management methods

142

*/

143

interface GroupManagementMethods {

144

/** Select all options in a specific group */

145

selectGroup(group: any): void;

146

147

/** Check if all options in a group are selected */

148

wholeGroupSelected(group: any): boolean;

149

150

/** Check if all options in a group are disabled */

151

wholeGroupDisabled(group: any): boolean;

152

153

/** Get CSS classes for group highlighting */

154

groupHighlight(index: number, group: any): string;

155

}

156

```

157

158

### Advanced Group Structure

159

160

Handle complex nested group structures with metadata.

161

162

```vue

163

<template>

164

<VueMultiselect

165

v-model="selectedCourses"

166

:options="courseGroups"

167

:multiple="true"

168

:group-values="'courses'"

169

:group-label="'subject'"

170

:group-select="true"

171

label="title"

172

track-by="code"

173

placeholder="Select courses">

174

175

<template #option="{ option }">

176

<div class="course-option">

177

<span class="course-title">{{ option.title }}</span>

178

<span class="course-credits">{{ option.credits }} credits</span>

179

<span class="course-level">Level {{ option.level }}</span>

180

</div>

181

</template>

182

183

<template #tag="{ option, remove }">

184

<span class="course-tag">

185

{{ option.code }}: {{ option.title }}

186

<button @click="remove(option)">×</button>

187

</span>

188

</template>

189

</VueMultiselect>

190

</template>

191

192

<script>

193

export default {

194

data() {

195

return {

196

selectedCourses: [],

197

courseGroups: [

198

{

199

subject: 'Computer Science',

200

totalCredits: 24,

201

courses: [

202

{

203

code: 'CS101',

204

title: 'Introduction to Programming',

205

credits: 4,

206

level: 1,

207

prerequisites: []

208

},

209

{

210

code: 'CS201',

211

title: 'Data Structures',

212

credits: 4,

213

level: 2,

214

prerequisites: ['CS101']

215

}

216

]

217

},

218

{

219

subject: 'Mathematics',

220

totalCredits: 16,

221

courses: [

222

{

223

code: 'MATH101',

224

title: 'Calculus I',

225

credits: 4,

226

level: 1,

227

prerequisites: []

228

},

229

{

230

code: 'MATH201',

231

title: 'Linear Algebra',

232

credits: 4,

233

level: 2,

234

prerequisites: ['MATH101']

235

}

236

]

237

}

238

]

239

}

240

}

241

}

242

</script>

243

244

<style>

245

.course-option {

246

display: flex;

247

justify-content: space-between;

248

align-items: center;

249

padding: 4px 0;

250

}

251

252

.course-title {

253

font-weight: 500;

254

}

255

256

.course-credits, .course-level {

257

font-size: 12px;

258

color: #666;

259

}

260

261

.course-tag {

262

display: inline-flex;

263

align-items: center;

264

gap: 4px;

265

padding: 2px 6px;

266

background: #e3f2fd;

267

border-radius: 3px;

268

font-size: 12px;

269

}

270

</style>

271

```

272

273

### Group Filtering

274

275

Apply search and filtering to grouped options.

276

277

```vue

278

<template>

279

<VueMultiselect

280

v-model="selectedProducts"

281

:options="productGroups"

282

:multiple="true"

283

:searchable="true"

284

:group-values="'products'"

285

:group-label="'category'"

286

:group-select="true"

287

label="name"

288

track-by="sku"

289

placeholder="Search products by category">

290

</VueMultiselect>

291

</template>

292

293

<script>

294

export default {

295

data() {

296

return {

297

selectedProducts: [],

298

productGroups: [

299

{

300

category: 'Electronics',

301

products: [

302

{ sku: 'EL001', name: 'Smartphone', price: 699 },

303

{ sku: 'EL002', name: 'Laptop', price: 1299 },

304

{ sku: 'EL003', name: 'Headphones', price: 199 }

305

]

306

},

307

{

308

category: 'Books',

309

products: [

310

{ sku: 'BK001', name: 'JavaScript Guide', price: 39 },

311

{ sku: 'BK002', name: 'Vue.js Cookbook', price: 45 }

312

]

313

}

314

]

315

}

316

}

317

}

318

</script>

319

```

320

321

### Custom Group Rendering

322

323

Customize the appearance of group headers and options.

324

325

```vue

326

<template>

327

<VueMultiselect

328

v-model="selectedTeamMembers"

329

:options="teams"

330

:multiple="true"

331

:group-values="'members'"

332

:group-label="'teamName'"

333

:group-select="true"

334

label="name"

335

track-by="id">

336

337

<template #beforeList>

338

<div class="team-stats">

339

<strong>{{ selectedTeamMembers.length }}</strong> members selected

340

</div>

341

</template>

342

343

<template #option="{ option, search }">

344

<div class="team-member-option">

345

<img :src="option.avatar" :alt="option.name" class="member-avatar">

346

<div class="member-info">

347

<div class="member-name">{{ option.name }}</div>

348

<div class="member-role">{{ option.role }}</div>

349

<div class="member-email">{{ option.email }}</div>

350

</div>

351

<div class="member-status" :class="option.status">

352

{{ option.status }}

353

</div>

354

</div>

355

</template>

356

357

<template #tag="{ option, remove }">

358

<span class="member-tag">

359

<img :src="option.avatar" :alt="option.name" class="tag-avatar">

360

{{ option.name }}

361

<button @click="remove(option)" class="remove-btn">×</button>

362

</span>

363

</template>

364

</VueMultiselect>

365

</template>

366

367

<script>

368

export default {

369

data() {

370

return {

371

selectedTeamMembers: [],

372

teams: [

373

{

374

teamName: 'Frontend Team',

375

teamLead: 'Alice Johnson',

376

members: [

377

{

378

id: 1,

379

name: 'Alice Johnson',

380

role: 'Team Lead',

381

email: 'alice@company.com',

382

avatar: '/avatars/alice.jpg',

383

status: 'online'

384

},

385

{

386

id: 2,

387

name: 'Bob Smith',

388

role: 'Senior Developer',

389

email: 'bob@company.com',

390

avatar: '/avatars/bob.jpg',

391

status: 'away'

392

}

393

]

394

},

395

{

396

teamName: 'Backend Team',

397

teamLead: 'Charlie Brown',

398

members: [

399

{

400

id: 3,

401

name: 'Charlie Brown',

402

role: 'Team Lead',

403

email: 'charlie@company.com',

404

avatar: '/avatars/charlie.jpg',

405

status: 'online'

406

}

407

]

408

}

409

]

410

}

411

}

412

}

413

</script>

414

415

<style>

416

.team-stats {

417

padding: 8px 12px;

418

background: #f5f5f5;

419

border-bottom: 1px solid #ddd;

420

font-size: 12px;

421

}

422

423

.team-member-option {

424

display: flex;

425

align-items: center;

426

padding: 8px 12px;

427

gap: 12px;

428

}

429

430

.member-avatar, .tag-avatar {

431

width: 32px;

432

height: 32px;

433

border-radius: 50%;

434

object-fit: cover;

435

}

436

437

.tag-avatar {

438

width: 20px;

439

height: 20px;

440

}

441

442

.member-info {

443

flex: 1;

444

}

445

446

.member-name {

447

font-weight: 500;

448

font-size: 14px;

449

}

450

451

.member-role {

452

font-size: 12px;

453

color: #666;

454

}

455

456

.member-email {

457

font-size: 11px;

458

color: #999;

459

}

460

461

.member-status {

462

padding: 2px 6px;

463

border-radius: 10px;

464

font-size: 10px;

465

text-transform: uppercase;

466

}

467

468

.member-status.online {

469

background: #4caf50;

470

color: white;

471

}

472

473

.member-status.away {

474

background: #ff9800;

475

color: white;

476

}

477

478

.member-tag {

479

display: inline-flex;

480

align-items: center;

481

gap: 6px;

482

padding: 4px 8px;

483

background: #e3f2fd;

484

border-radius: 16px;

485

font-size: 12px;

486

}

487

488

.remove-btn {

489

background: none;

490

border: none;

491

cursor: pointer;

492

font-size: 16px;

493

color: #666;

494

padding: 0;

495

margin-left: 4px;

496

}

497

</style>

498

```

499

500

### Group Events

501

502

Events specific to group operations.

503

504

```typescript { .api }

505

/**

506

* Group-related events

507

*/

508

interface GroupEvents {

509

/** Emitted when a group is selected/deselected */

510

'@group-select': (group: any, selectedMembers: any[]) => void;

511

512

/** Emitted when group selection state changes */

513

'@group-change': (group: any, isSelected: boolean) => void;

514

}

515

```

516

517

### Disabled Groups

518

519

Handle disabled state for entire groups or individual options within groups.

520

521

```vue

522

<template>

523

<VueMultiselect

524

v-model="selectedFeatures"

525

:options="featureGroups"

526

:multiple="true"

527

:group-values="'features'"

528

:group-label="'plan'"

529

:group-select="true"

530

label="name"

531

track-by="id">

532

533

<template #option="{ option }">

534

<div class="feature-option" :class="{ disabled: option.disabled }">

535

<span>{{ option.name }}</span>

536

<span v-if="option.disabled" class="disabled-reason">

537

({{ option.disabledReason }})

538

</span>

539

</div>

540

</template>

541

</VueMultiselect>

542

</template>

543

544

<script>

545

export default {

546

data() {

547

return {

548

selectedFeatures: [],

549

featureGroups: [

550

{

551

plan: 'Basic Plan',

552

features: [

553

{ id: 1, name: 'Email Support', disabled: false },

554

{ id: 2, name: 'Basic Analytics', disabled: false }

555

]

556

},

557

{

558

plan: 'Premium Plan',

559

features: [

560

{

561

id: 3,

562

name: 'Priority Support',

563

disabled: true,

564

disabledReason: 'Upgrade required'

565

},

566

{

567

id: 4,

568

name: 'Advanced Analytics',

569

disabled: true,

570

disabledReason: 'Upgrade required'

571

}

572

]

573

}

574

]

575

}

576

}

577

}

578

</script>

579

580

<style>

581

.feature-option.disabled {

582

opacity: 0.5;

583

cursor: not-allowed;

584

}

585

586

.disabled-reason {

587

font-size: 11px;

588

color: #999;

589

font-style: italic;

590

}

591

</style>

592

```