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

dynamic-component.mddocs/

0

# Dynamic Component Creation

1

2

Core functionality for creating Angular components dynamically at runtime with full lifecycle support, custom injectors, and projected content.

3

4

## Capabilities

5

6

### DynamicComponent

7

8

The main component for dynamically creating other Angular components at runtime.

9

10

```typescript { .api }

11

/**

12

* Main component for dynamically creating other Angular components

13

* Supports full component lifecycle, custom injection, and projected content

14

*/

15

@Component({

16

selector: 'ndc-dynamic',

17

standalone: true,

18

template: '',

19

providers: [

20

{ provide: DynamicComponentInjectorToken, useExisting: DynamicComponent }

21

]

22

})

23

export class DynamicComponent<C = unknown> implements OnChanges, DynamicComponentInjector {

24

/** The component type to create dynamically */

25

@Input() ndcDynamicComponent?: Type<C> | null;

26

27

/** Custom injector for the dynamic component */

28

@Input() ndcDynamicInjector?: Injector | null;

29

30

/** Additional providers for the dynamic component */

31

@Input() ndcDynamicProviders?: StaticProvider[] | null;

32

33

/** Projected content (projectable nodes) for content projection */

34

@Input() ndcDynamicContent?: Node[][];

35

36

/** NgModule reference for the component (for legacy non-standalone components) */

37

@Input() ndcDynamicNgModuleRef?: NgModuleRef<unknown>;

38

39

/** Environment injector for standalone components */

40

@Input() ndcDynamicEnvironmentInjector?: EnvironmentInjector | NgModuleRef<unknown>;

41

42

/** Emitted when a component is created */

43

@Output() ndcDynamicCreated: EventEmitter<ComponentRef<C>>;

44

45

/** Reference to the currently created component */

46

componentRef: ComponentRef<C> | null;

47

48

/** Manually trigger component creation */

49

createDynamicComponent(): void;

50

}

51

```

52

53

**Usage Examples:**

54

55

```typescript

56

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

57

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

58

59

// Basic dynamic component creation

60

@Component({

61

selector: 'app-basic-example',

62

template: `

63

<ndc-dynamic

64

[ndcDynamicComponent]="selectedComponent"

65

(ndcDynamicCreated)="onComponentCreated($event)">

66

</ndc-dynamic>

67

`

68

})

69

export class BasicExampleComponent {

70

selectedComponent: Type<any> = MyDynamicComponent;

71

72

onComponentCreated(componentRef: ComponentRef<any>) {

73

// Access the component instance

74

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

75

76

// Set inputs directly on the component

77

componentRef.instance.title = 'Dynamic Title';

78

79

// Trigger change detection

80

componentRef.changeDetectorRef.detectChanges();

81

}

82

}

83

84

// Advanced usage with custom injector and providers

85

@Component({

86

selector: 'app-advanced-example',

87

template: `

88

<ndc-dynamic

89

[ndcDynamicComponent]="componentType"

90

[ndcDynamicInjector]="customInjector"

91

[ndcDynamicProviders]="providers"

92

[ndcDynamicContent]="projectedContent"

93

(ndcDynamicCreated)="handleCreated($event)">

94

</ndc-dynamic>

95

`

96

})

97

export class AdvancedExampleComponent {

98

componentType = CustomComponent;

99

customInjector?: Injector;

100

providers = [

101

{ provide: 'CONFIG', useValue: { apiUrl: 'https://api.example.com' } },

102

{ provide: MyService, useClass: MyService }

103

];

104

projectedContent?: Node[][];

105

106

constructor(private injector: Injector) {

107

// Create custom injector

108

this.customInjector = Injector.create({

109

providers: [

110

{ provide: 'CUSTOM_TOKEN', useValue: 'custom-value' }

111

],

112

parent: this.injector

113

});

114

}

115

116

handleCreated(componentRef: ComponentRef<CustomComponent>) {

117

// Component is created with custom injection context

118

componentRef.instance.initialize();

119

}

120

}

121

122

// Content projection example

123

@Component({

124

selector: 'app-projection-example',

125

template: `

126

<ndc-dynamic

127

[ndcDynamicComponent]="wrapperComponent"

128

[ndcDynamicContent]="contentNodes">

129

</ndc-dynamic>

130

`

131

})

132

export class ProjectionExampleComponent implements AfterViewInit {

133

wrapperComponent = WrapperComponent;

134

contentNodes?: Node[][];

135

136

@ViewChild('content', { read: ElementRef }) contentEl!: ElementRef;

137

138

ngAfterViewInit() {

139

// Create content to project

140

this.contentNodes = [

141

[this.contentEl.nativeElement.childNodes[0]]

142

];

143

}

144

}

145

```

146

147

### Component Type Switching

148

149

Dynamically switch between different component types:

150

151

```typescript

152

@Component({

153

template: `

154

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

155

156

<ndc-dynamic

157

[ndcDynamicComponent]="currentComponent"

158

(ndcDynamicCreated)="onCreated($event)">

159

</ndc-dynamic>

160

`

161

})

162

export class ComponentSwitcherComponent {

163

private components = [ComponentA, ComponentB, ComponentC];

164

private currentIndex = 0;

165

166

get currentComponent() {

167

return this.components[this.currentIndex];

168

}

169

170

switchComponent() {

171

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

172

}

173

174

onCreated(componentRef: ComponentRef<any>) {

175

console.log('Switched to:', componentRef.componentType.name);

176

}

177

}

178

```

179

180

### Working with Standalone Components

181

182

For standalone components, use the environment injector:

183

184

```typescript

185

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

186

187

@Component({

188

template: `

189

<ndc-dynamic

190

[ndcDynamicComponent]="standaloneComponent"

191

[ndcDynamicEnvironmentInjector]="environmentInjector">

192

</ndc-dynamic>

193

`

194

})

195

export class StandaloneExampleComponent {

196

standaloneComponent = MyStandaloneComponent;

197

198

constructor(public environmentInjector: EnvironmentInjector) {}

199

}

200

```

201

202

### Integration with Dynamic I/O

203

204

Combine with dynamic input/output directives for complete functionality:

205

206

```typescript

207

import { DynamicComponent, DynamicIoDirective } from 'ng-dynamic-component';

208

209

@Component({

210

standalone: true,

211

imports: [DynamicComponent, DynamicIoDirective],

212

template: `

213

<ndc-dynamic

214

[ndcDynamicComponent]="component"

215

[ndcDynamicInputs]="inputs"

216

[ndcDynamicOutputs]="outputs"

217

(ndcDynamicCreated)="onCreated($event)">

218

</ndc-dynamic>

219

`

220

})

221

export class FullExampleComponent {

222

component = MyComponent;

223

inputs = { title: 'Hello', data: [1, 2, 3] };

224

outputs = {

225

onSave: (data: any) => console.log('Saved:', data),

226

onDelete: () => console.log('Deleted')

227

};

228

229

onCreated(componentRef: ComponentRef<any>) {

230

// Component is created with inputs/outputs bound

231

}

232

}

233

```

234

235

## Types

236

237

```typescript { .api }

238

/** Interface for objects that can provide ComponentRef access */

239

interface DynamicComponentInjector {

240

componentRef: ComponentRef<unknown> | null;

241

}

242

243

/** Injection token for DynamicComponentInjector */

244

const DynamicComponentInjectorToken: InjectionToken<DynamicComponentInjector>;

245

```