or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

component-management.mddata-display-components.mdfeedback-components.mdform-components.mdindex.mdlayout-components.mdnavigation-components.mdvisual-effects.md

component-management.mddocs/

0

# Component Management

1

2

Core system for managing Material Design Lite component lifecycle, registration, and upgrades. The component handler provides centralized control over when and how MDL components are initialized and managed.

3

4

## Capabilities

5

6

### Component Handler

7

8

The global `componentHandler` object provides the main API for component lifecycle management.

9

10

```javascript { .api }

11

/**

12

* Global component handler for managing MDL components

13

* Available as window.componentHandler

14

*/

15

interface ComponentHandler {

16

/**

17

* Searches existing DOM for elements of specified component type and upgrades them

18

* @param optJsClass - Optional programmatic name of the element class to upgrade

19

* @param optCssClass - Optional CSS class name of elements to upgrade

20

*/

21

upgradeDom(optJsClass?: string, optCssClass?: string): void;

22

23

/**

24

* Upgrades a specific element rather than all in the DOM

25

* @param element - The element to upgrade

26

* @param optJsClass - Optional name of the class to upgrade the element to

27

*/

28

upgradeElement(element: Element, optJsClass?: string): void;

29

30

/**

31

* Upgrades a specific list of elements rather than all in the DOM

32

* @param elements - The elements to upgrade

33

*/

34

upgradeElements(elements: Element[] | NodeList | HTMLCollection): void;

35

36

/**

37

* Upgrades all registered components found in the current DOM

38

* Automatically called on window load

39

*/

40

upgradeAllRegistered(): void;

41

42

/**

43

* Allows user to be alerted to any upgrades performed for a given component type

44

* @param jsClass - The class name of the MDL component to hook into

45

* @param callback - Function to call upon upgrade, receives HTMLElement parameter

46

*/

47

registerUpgradedCallback(jsClass: string, callback: (element: HTMLElement) => void): void;

48

49

/**

50

* Registers a class for future use and attempts to upgrade existing DOM

51

* @param config - The registration configuration

52

*/

53

register(config: ComponentConfigPublic): void;

54

55

/**

56

* Downgrade either a given node, an array of nodes, or a NodeList

57

* @param nodes - The nodes to downgrade

58

*/

59

downgradeElements(nodes: Node[] | NodeList): void;

60

}

61

```

62

63

**Usage Examples:**

64

65

```javascript

66

// Upgrade all MDL components in the DOM

67

componentHandler.upgradeAllRegistered();

68

69

// Upgrade specific component type

70

componentHandler.upgradeDom('MaterialButton', 'mdl-js-button');

71

72

// Upgrade a single element

73

const newButton = document.querySelector('.mdl-js-button');

74

componentHandler.upgradeElement(newButton);

75

76

// Upgrade multiple elements

77

const buttons = document.querySelectorAll('.mdl-js-button');

78

componentHandler.upgradeElements(buttons);

79

80

// Register callback for component upgrades

81

componentHandler.registerUpgradedCallback('MaterialButton', (element) => {

82

console.log('Button upgraded:', element);

83

});

84

85

// Clean up components when removing elements

86

const elementToRemove = document.querySelector('.mdl-js-button');

87

componentHandler.downgradeElements([elementToRemove]);

88

elementToRemove.parentNode.removeChild(elementToRemove);

89

```

90

91

### Component Registration

92

93

Register new component types with the component handler.

94

95

```javascript { .api }

96

/**

97

* Configuration for registering a new component type

98

*/

99

interface ComponentConfigPublic {

100

/** Constructor function for the component */

101

constructor: Function;

102

/** String representation of the class name */

103

classAsString: string;

104

/** CSS class that identifies elements of this component type */

105

cssClass: string;

106

/** Whether the component should be accessible as a widget (default: true) */

107

widget?: boolean;

108

}

109

110

/**

111

* Internal configuration structure (for reference)

112

*/

113

interface ComponentConfig {

114

classConstructor: Function;

115

className: string;

116

cssClass: string;

117

widget: boolean;

118

callbacks: Array<(element: HTMLElement) => void>;

119

}

120

```

121

122

**Usage Examples:**

123

124

```javascript

125

// Register a custom component

126

function MyCustomComponent(element) {

127

this.element_ = element;

128

this.init();

129

}

130

131

MyCustomComponent.prototype.init = function() {

132

// Component initialization logic

133

};

134

135

MyCustomComponent.prototype.myMethod = function() {

136

// Custom component method

137

};

138

139

// Register with component handler

140

componentHandler.register({

141

constructor: MyCustomComponent,

142

classAsString: 'MyCustomComponent',

143

cssClass: 'my-js-component',

144

widget: true

145

});

146

147

// Now elements with 'my-js-component' class will be automatically upgraded

148

```

149

150

### Component Events

151

152

Components emit events during their lifecycle that can be listened to for custom behavior.

153

154

```javascript { .api }

155

/**

156

* Event fired before a component is upgraded

157

* Can be cancelled by calling preventDefault()

158

*/

159

interface MDLComponentUpgradingEvent extends CustomEvent {

160

type: 'mdl-componentupgrading';

161

bubbles: true;

162

cancelable: true;

163

}

164

165

/**

166

* Event fired after a component has been upgraded

167

*/

168

interface MDLComponentUpgradedEvent extends CustomEvent {

169

type: 'mdl-componentupgraded';

170

bubbles: true;

171

cancelable: false;

172

}

173

174

/**

175

* Event fired after a component has been downgraded

176

*/

177

interface MDLComponentDowngradedEvent extends CustomEvent {

178

type: 'mdl-componentdowngraded';

179

bubbles: true;

180

cancelable: false;

181

}

182

```

183

184

**Usage Examples:**

185

186

```javascript

187

// Listen for component upgrade events

188

document.addEventListener('mdl-componentupgrading', (event) => {

189

console.log('Component about to upgrade:', event.target);

190

191

// Cancel upgrade if needed

192

if (shouldCancelUpgrade(event.target)) {

193

event.preventDefault();

194

}

195

});

196

197

document.addEventListener('mdl-componentupgraded', (event) => {

198

console.log('Component upgraded:', event.target);

199

200

// Perform post-upgrade actions

201

setupCustomBehavior(event.target);

202

});

203

204

document.addEventListener('mdl-componentdowngraded', (event) => {

205

console.log('Component downgraded:', event.target);

206

207

// Clean up any custom behavior

208

cleanupCustomBehavior(event.target);

209

});

210

```

211

212

### Component Instance Management

213

214

Access and manage component instances on upgraded elements.

215

216

```javascript { .api }

217

/**

218

* Component instance structure (for widget components)

219

*/

220

interface Component {

221

/** The DOM element this component is attached to */

222

element_: HTMLElement;

223

/** The component class name */

224

className: string;

225

/** String representation of the class */

226

classAsString: string;

227

/** CSS class that identifies this component type */

228

cssClass: string;

229

/** Widget identifier */

230

widget: string;

231

}

232

```

233

234

**Usage Examples:**

235

236

```javascript

237

// Access widget component instances

238

const buttonElement = document.querySelector('.mdl-js-button');

239

const buttonInstance = buttonElement.MaterialButton;

240

241

if (buttonInstance) {

242

// Use component methods

243

buttonInstance.disable();

244

}

245

246

// Check if element has been upgraded

247

const textfieldElement = document.querySelector('.mdl-js-textfield');

248

if (textfieldElement.MaterialTextfield) {

249

console.log('Textfield is already upgraded');

250

textfieldElement.MaterialTextfield.checkValidity();

251

} else {

252

console.log('Textfield needs to be upgraded');

253

componentHandler.upgradeElement(textfieldElement);

254

}

255

256

// List all upgraded components on an element

257

const upgradedList = element.getAttribute('data-upgraded');

258

console.log('Upgraded components:', upgradedList ? upgradedList.split(',') : []);

259

```

260

261

### Error Handling

262

263

Handle errors that may occur during component management operations.

264

265

```javascript

266

// Component upgrade errors

267

try {

268

componentHandler.upgradeElement(invalidElement);

269

} catch (error) {

270

if (error.message.includes('Invalid argument provided')) {

271

console.error('Element is not a valid DOM element');

272

} else if (error.message.includes('Unable to find a registered component')) {

273

console.error('Component class not registered');

274

} else {

275

console.error('Unknown upgrade error:', error);

276

}

277

}

278

279

// Registration errors

280

try {

281

componentHandler.register({

282

constructor: MyComponent,

283

classAsString: 'ExistingComponent', // This will throw if already registered

284

cssClass: 'my-component'

285

});

286

} catch (error) {

287

if (error.message.includes('already been registered')) {

288

console.error('Component already registered');

289

}

290

}

291

```

292

293

## Best Practices

294

295

### Dynamic Content

296

297

When adding MDL components dynamically:

298

299

```javascript

300

// Create element with MDL classes

301

const dynamicElement = document.createElement('button');

302

dynamicElement.className = 'mdl-button mdl-js-button mdl-button--raised';

303

dynamicElement.textContent = 'Dynamic Button';

304

305

// Add to DOM first

306

document.body.appendChild(dynamicElement);

307

308

// Then upgrade

309

componentHandler.upgradeElement(dynamicElement);

310

311

// For multiple elements

312

const elements = [element1, element2, element3];

313

elements.forEach(el => document.body.appendChild(el));

314

componentHandler.upgradeElements(elements);

315

```

316

317

### Memory Management

318

319

Clean up components when removing elements:

320

321

```javascript

322

// Before removing elements from DOM

323

const elementToRemove = document.querySelector('.mdl-js-button');

324

componentHandler.downgradeElements([elementToRemove]);

325

elementToRemove.parentNode.removeChild(elementToRemove);

326

327

// For single page applications

328

function cleanupPage() {

329

const allMDLElements = document.querySelectorAll('[data-upgraded]');

330

componentHandler.downgradeElements(allMDLElements);

331

}

332

```

333

334

### Performance

335

336

Optimize component upgrades:

337

338

```javascript

339

// Batch upgrades when possible

340

const newElements = [];

341

for (let i = 0; i < 10; i++) {

342

const el = createMDLElement();

343

container.appendChild(el);

344

newElements.push(el);

345

}

346

componentHandler.upgradeElements(newElements);

347

348

// Use specific component types when known

349

componentHandler.upgradeDom('MaterialButton', 'mdl-js-button');

350

```