Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lacolaco/ng-dynamic
dynamic contents projection in Angular
https://github.com/lacolaco/ng-dynamic
angular
Last synced: about 1 month ago
JSON representation
dynamic contents projection in Angular
- Host: GitHub
- URL: https://github.com/lacolaco/ng-dynamic
- Owner: lacolaco
- Archived: true
- Created: 2016-11-14T04:53:15.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2019-05-17T13:54:18.000Z (over 5 years ago)
- Last Synced: 2024-05-12T23:42:21.859Z (7 months ago)
- Topics: angular
- Language: TypeScript
- Homepage:
- Size: 52.7 KB
- Stars: 132
- Watchers: 16
- Forks: 34
- Open Issues: 18
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-angular-components - ng-dynamic - Dynamic Content Projection in Angular 2+ (Uncategorized / Uncategorized)
README
# THIS REPOSITORY IS NOT MAINTAINED
# ng-dynamic
## Since Angular 4.0, AoT compiler cannot coexist with JiT compiler. If you want to use DynamicComponentModule, you cannot use AoT compilation.
Dynamic Content Projection in Angular 2+
[![npm version](https://badge.fury.io/js/ng-dynamic.svg)](https://badge.fury.io/js/ng-dynamic)
[![CircleCI](https://circleci.com/gh/lacolaco/ng-dynamic/tree/master.svg?style=svg)](https://circleci.com/gh/lacolaco/ng-dynamic/tree/master)```
$ npm install --save ng-dynamic
```**Live Demo**: [Plunker](https://plnkr.co/edit/uzcYiN?p=preview)
---
## 'dynamic' means...
We often need to project some _dynamic contents_ into your Angular app. For example, if you make a markdown editor, you want to display the rendererd preview.
```ts
',
@Component({
selector: 'html-preview',
template: '
})
export class HTMLPreviewComponent {
@Input() html: string;
}
```This code has some problems:
- `[innerHTML]` will sanitize its value and strip some elements.
- in innerHTML, any Angular components like `` don't work.**ng-dynamic** can solve these problems by using standard Angular APIs and some _hacks_.
### ``
`` is a component to render given HTML string and **mount** components in the HTML.
Example:
```ts
@Component({
selector: 'my-button',
template: `Click Me`
})
export class MyButtonComponent {
onClick() {
}
}@Component({
selector: 'my-app',
template: `
`
})
export class AppComponent {
content = `
Awesome Document
bla bla bla
`;
}@NgModule({
imports: [
DynamicHTMLModule.forRoot({
components: [
{ component: MyButtonComponent, selector: 'my-button' },
]
})
],
declarations: [AppComponent, MyButtonComponent],
bootstrap: [AppComponent]
})
export class AppModule {
}
```Result:
```html
Awesome Document
bla bla bla
Click Me
```
`` is resolved as `MyButtonComponent`.
#### `DynamicHTMLModule`
To use ``, you have to import `DynamicHTMLModule` with `forRoot` static method.
Its argument is a `DynamicHTMLOptions` object:```ts
/**
* defines dynamic-projectable components
*
* ```ts
* @Component({
* selector: 'child-cmp',
* template: `child:{{text}}
`,
* })
* class ChildCmp {
* @Input() text: string;
* }
*
* DynamicHTMLModule.forRoot({
* components: [
* { component: ChildCmp, selector: 'child-cmp' } },
* ]
* })
* ```
*/
export interface ComponentWithSelector {
/**
* component's selector
*/
selector: string;
/**
* component's type
*/
component: Type;
}/**
* options for DynamicHTMLModule
*/
export class DynamicHTMLOptions {
/**
* identifies components projected in dynamic HTML.
*/
components: Array;
}
```#### `OnMount` Lifecycle method
```ts
/**
* Lifecycle hook that is called after instantiation the component.
* This method is called before ngOnInit.
*/
export abstract class OnMount {
abstract dynamicOnMount(attrs?: Map, innerHTML?: string, element?: Element): void;
}
````OnMount` allows you to create component has _hybrid content projection_.
_hybrid content projection_ means that the component can project its content from even _static_ template or _dynamic_ HTML.See also demo.
```ts
@Component({
selector: 'awesome-button',
template: ``,
})
export class AwesomeButtonComponent implements OnMount, OnInit {
@Input() msg: string;
@ViewChild('innerContent') innerContent: ElementRef;dynamicOnMount(attr: Map, content: string) {
this.msg = attr.get('msg');
this.innerContent.nativeElement.innerHTML = content;
console.log(`onMount: ${this.msg}`);
}ngOnInit() {
console.log(`onInit: ${this.msg}`);
}onClick() {
console.log('clicked');
}
}
```#### `` Constraints
- `[content]` is **not a template**. so it cannot resolve `{{foo}}`, `*ngIf` and any template syntax.
### `*dynamicComponent="template"`
`dynamicComponent` is a directive to create dynamic component which has the template.
Example:
```ts
@Component({
selector: 'dynamic-cmp-demo',
template: `
`,
})
export class DynamicCmpDemoComponent {
template = `
Awesome Document
{{text}}
`;text = 'foo';
}@NgModule({
imports: [
CommonModule,
],
declarations: [
MyComponent
],
exports: [
MyComponent
]
})
export class SharedModule { }@NgModule({
imports: [
BrowserModule,
FormsModule,
SharedModule,
DynamicComponentModule.forRoot({
imports: [SharedModule]
}),
],
declarations: [
AppComponent,
DynamicCmpDemoComponent,
],
bootstrap: [AppComponent]
})
export class AppModule {
}
```Result:
```html
Awesome Document
foo
Click Me
```
`` is resolved as `MyButtonComponent`.
#### `DynamicComponentModule`
To use `dynamicComponent`, you have to import `DynamicComponentModule` with `forRoot` static method.
Its argument is a `NgModule` metadata object:```ts
/**
* Setup for DynamicComponentDirective
*
* ```ts
* @NgModule({
* imports: [
* DynamicComponentModule.forRoot({
* imports: [CommonModule]
* })
* ],
* })
* class AppModule {}
* ```
*/
```#### `dynamicComponent` Constraints
`dynamicComponent` needs `JitCompiler`. You cannot use AoT compilation with DynamicComponentModule.
## License
MIT## Developing
```
npm i && npm run demo # and open http://localhost:8080
```Contributions welcome!