or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

component-outlet.mdcore-services.mddynamic-attributes.mddynamic-component.mddynamic-directives.mdindex.mdinput-output.md

component-outlet.mddocs/

0

# NgComponentOutlet Enhancement

1

2

Directives that extend Angular's built-in NgComponentOutlet with dynamic input/output binding, component reference access, and additional lifecycle management capabilities.

3

4

## Capabilities

5

6

### Component Outlet Injector Directive

7

8

Provides access to the ComponentRef created by NgComponentOutlet for further manipulation and lifecycle management.

9

10

```typescript { .api }

11

/**

12

* Provides ComponentRef access for NgComponentOutlet

13

* Enables accessing the component instance created by the outlet

14

*/

15

@Directive({

16

selector: '[ngComponentOutlet]',

17

standalone: true,

18

exportAs: 'ndcComponentOutletInjector'

19

})

20

export class ComponentOutletInjectorDirective {

21

/**

22

* Reference to the component created by NgComponentOutlet

23

* Provides access to the component instance and lifecycle methods

24

*/

25

readonly componentRef: ComponentRef<unknown>;

26

}

27

```

28

29

### Component Outlet I/O Directive

30

31

Enables dynamic input/output binding for components created by NgComponentOutlet.

32

33

```typescript { .api }

34

/**

35

* Enables dynamic inputs/outputs for NgComponentOutlet

36

* Works in conjunction with Angular's built-in outlet directive

37

*/

38

@Directive({

39

selector: '[ngComponentOutletNdcDynamicInputs],[ngComponentOutletNdcDynamicOutputs]',

40

standalone: true,

41

exportAs: 'ndcDynamicIo'

42

})

43

export class ComponentOutletIoDirective implements DoCheck {

44

/** Dynamic inputs for the outlet component */

45

@Input() ngComponentOutletNdcDynamicInputs?: InputsType | null;

46

47

/** Dynamic outputs for the outlet component */

48

@Input() ngComponentOutletNdcDynamicOutputs?: OutputsType | null;

49

}

50

```

51

52

### Component Outlet Injector Module

53

54

NgModule that provides both outlet enhancement directives for traditional module-based applications.

55

56

```typescript { .api }

57

/**

58

* Module that exports both outlet enhancement directives

59

* Use this in NgModule-based applications

60

*/

61

@NgModule({

62

imports: [ComponentOutletInjectorDirective, ComponentOutletIoDirective],

63

exports: [ComponentOutletInjectorDirective, ComponentOutletIoDirective]

64

})

65

export class ComponentOutletInjectorModule {}

66

```

67

68

**Usage Examples:**

69

70

```typescript

71

import { Component, Type, ComponentRef } from '@angular/core';

72

import { ComponentOutletInjectorDirective, ComponentOutletIoDirective } from 'ng-dynamic-component';

73

74

// Basic outlet with component reference access

75

@Component({

76

standalone: true,

77

imports: [ComponentOutletInjectorDirective],

78

template: `

79

<ng-container

80

*ngComponentOutlet="selectedComponent"

81

#outlet="ndcComponentOutletInjector">

82

</ng-container>

83

84

<button (click)="accessComponent(outlet.componentRef)">

85

Access Component

86

</button>

87

`

88

})

89

export class OutletBasicExampleComponent {

90

selectedComponent: Type<any> = MyComponent;

91

92

accessComponent(componentRef: ComponentRef<any>) {

93

console.log('Component instance:', componentRef.instance);

94

95

// Directly modify component properties

96

componentRef.instance.title = 'Modified Title';

97

98

// Trigger change detection

99

componentRef.changeDetectorRef.detectChanges();

100

101

// Access component methods

102

if (typeof componentRef.instance.refresh === 'function') {

103

componentRef.instance.refresh();

104

}

105

}

106

}

107

108

// Outlet with dynamic I/O binding

109

@Component({

110

standalone: true,

111

imports: [ComponentOutletIoDirective],

112

template: `

113

<ng-container

114

*ngComponentOutlet="componentType"

115

[ngComponentOutletNdcDynamicInputs]="inputs"

116

[ngComponentOutletNdcDynamicOutputs]="outputs">

117

</ng-container>

118

`

119

})

120

export class OutletIoExampleComponent {

121

componentType = UserProfileComponent;

122

123

inputs = {

124

userId: 123,

125

editMode: false,

126

theme: 'light'

127

};

128

129

outputs = {

130

onSave: (userData: any) => this.saveUser(userData),

131

onCancel: () => this.cancelEdit(),

132

onProfilePictureChange: (imageUrl: string) => this.updateProfilePicture(imageUrl)

133

};

134

135

saveUser(userData: any) {

136

console.log('Saving user:', userData);

137

// Implement save logic

138

}

139

140

cancelEdit() {

141

console.log('Edit cancelled');

142

this.inputs = { ...this.inputs, editMode: false };

143

}

144

145

updateProfilePicture(imageUrl: string) {

146

console.log('Profile picture updated:', imageUrl);

147

// Handle image update

148

}

149

}

150

151

// Combined usage with both directives

152

@Component({

153

standalone: true,

154

imports: [ComponentOutletInjectorDirective, ComponentOutletIoDirective],

155

template: `

156

<ng-container

157

*ngComponentOutlet="currentComponent"

158

[ngComponentOutletNdcDynamicInputs]="dynamicInputs"

159

[ngComponentOutletNdcDynamicOutputs]="dynamicOutputs"

160

#outlet="ndcComponentOutletInjector">

161

</ng-container>

162

163

<div class="controls">

164

<button (click)="refreshComponent(outlet.componentRef)">Refresh</button>

165

<button (click)="switchComponent()">Switch Component</button>

166

</div>

167

`

168

})

169

export class OutletCombinedExampleComponent {

170

private components = [DashboardComponent, SettingsComponent, ProfileComponent];

171

private currentIndex = 0;

172

173

get currentComponent() {

174

return this.components[this.currentIndex];

175

}

176

177

get dynamicInputs() {

178

// Return different inputs based on current component

179

switch (this.currentComponent) {

180

case DashboardComponent:

181

return { userId: 123, refreshInterval: 5000 };

182

case SettingsComponent:

183

return { theme: 'dark', notifications: true };

184

case ProfileComponent:

185

return { userId: 123, editMode: false };

186

default:

187

return {};

188

}

189

}

190

191

get dynamicOutputs() {

192

return {

193

onAction: (action: string, data?: any) => this.handleAction(action, data),

194

onNavigate: (route: string) => this.navigate(route)

195

};

196

}

197

198

refreshComponent(componentRef: ComponentRef<any>) {

199

if (typeof componentRef.instance.refresh === 'function') {

200

componentRef.instance.refresh();

201

}

202

}

203

204

switchComponent() {

205

this.currentIndex = (this.currentIndex + 1) % this.components.length;

206

console.log('Switched to:', this.currentComponent.name);

207

}

208

209

handleAction(action: string, data?: any) {

210

console.log('Action received:', action, data);

211

}

212

213

navigate(route: string) {

214

console.log('Navigate to:', route);

215

// Implement navigation logic

216

}

217

}

218

```

219

220

### Working with Complex Component Hierarchies

221

222

Handle nested components and complex injection scenarios:

223

224

```typescript

225

@Component({

226

template: `

227

<div class="parent-container">

228

<ng-container

229

*ngComponentOutlet="

230

parentComponent;

231

injector: customInjector;

232

content: projectedNodes

233

"

234

[ngComponentOutletNdcDynamicInputs]="parentInputs"

235

[ngComponentOutletNdcDynamicOutputs]="parentOutputs"

236

#parentOutlet="ndcComponentOutletInjector">

237

</ng-container>

238

239

<!-- Child component that depends on parent -->

240

<ng-container

241

*ngComponentOutlet="childComponent"

242

[ngComponentOutletNdcDynamicInputs]="getChildInputs(parentOutlet.componentRef)"

243

[ngComponentOutletNdcDynamicOutputs]="childOutputs">

244

</ng-container>

245

</div>

246

`

247

})

248

export class HierarchicalOutletComponent {

249

parentComponent = ParentComponent;

250

childComponent = ChildComponent;

251

252

parentInputs = {

253

title: 'Parent Component',

254

configuration: { mode: 'advanced' }

255

};

256

257

parentOutputs = {

258

onConfigChange: (config: any) => this.updateConfiguration(config)

259

};

260

261

childOutputs = {

262

onChildEvent: (event: any) => this.handleChildEvent(event)

263

};

264

265

constructor(private injector: Injector) {}

266

267

get customInjector() {

268

return Injector.create({

269

providers: [

270

{ provide: 'PARENT_CONFIG', useValue: { theme: 'blue' } }

271

],

272

parent: this.injector

273

});

274

}

275

276

get projectedNodes() {

277

// Create content to project into parent component

278

return [

279

// Projected content nodes

280

];

281

}

282

283

getChildInputs(parentComponentRef: ComponentRef<any>) {

284

// Child inputs depend on parent component state

285

return {

286

parentData: parentComponentRef?.instance?.data || null,

287

inherited: true

288

};

289

}

290

291

updateConfiguration(config: any) {

292

console.log('Parent configuration updated:', config);

293

}

294

295

handleChildEvent(event: any) {

296

console.log('Child event received:', event);

297

}

298

}

299

```

300

301

### Integration with Angular Router

302

303

Use outlet components with router data and parameters:

304

305

```typescript

306

import { ActivatedRoute } from '@angular/router';

307

308

@Component({

309

template: `

310

<ng-container

311

*ngComponentOutlet="getComponentForRoute()"

312

[ngComponentOutletNdcDynamicInputs]="routeInputs"

313

[ngComponentOutletNdcDynamicOutputs]="routeOutputs">

314

</ng-container>

315

`

316

})

317

export class RoutedOutletComponent implements OnInit {

318

private routeData: any = {};

319

private routeParams: any = {};

320

321

constructor(private route: ActivatedRoute) {}

322

323

ngOnInit() {

324

// Subscribe to route data and parameters

325

this.route.data.subscribe(data => {

326

this.routeData = data;

327

});

328

329

this.route.params.subscribe(params => {

330

this.routeParams = params;

331

});

332

}

333

334

getComponentForRoute(): Type<any> {

335

// Select component based on route data

336

return this.routeData.component || DefaultComponent;

337

}

338

339

get routeInputs() {

340

return {

341

...this.routeParams,

342

routeData: this.routeData,

343

timestamp: Date.now()

344

};

345

}

346

347

get routeOutputs() {

348

return {

349

onRouteAction: (action: string) => this.handleRouteAction(action)

350

};

351

}

352

353

handleRouteAction(action: string) {

354

console.log('Route action:', action);

355

// Handle route-specific actions

356

}

357

}

358

```

359

360

## Module Usage

361

362

For NgModule-based applications:

363

364

```typescript

365

import { NgModule } from '@angular/core';

366

import { ComponentOutletInjectorModule } from 'ng-dynamic-component';

367

368

@NgModule({

369

imports: [

370

ComponentOutletInjectorModule

371

],

372

// Component can now use outlet directives

373

})

374

export class MyFeatureModule {}

375

```