• Stars
    star
    134
  • Rank 270,967 (Top 6 %)
  • Language
    TypeScript
  • Created about 8 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

dynamic contents projection in Angular

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 CircleCI

$ npm install --save ng-dynamic

Live Demo: Plunker


'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.

@Component({
  selector: 'html-preview',
  template: '<div [innerHTML]="html"></div>',
})
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 <my-button> don't work.

ng-dynamic can solve these problems by using standard Angular APIs and some hacks.

<dynamic-html [content]="html">

<dynamic-html> is a component to render given HTML string and mount components in the HTML.

Example:

@Component({
  selector: 'my-button',
  template: `<button (click)="onClick()">Click Me</button>`
})
export class MyButtonComponent {
  onClick() {
  }
}

@Component({
  selector: 'my-app',
  template: `
    <dynamic-html [content]="content"></dynamic-html>
  `
})
export class AppComponent {
  content = `
  <article>
    <h1>Awesome Document</h1>
    <div>
      <p>bla bla bla</p>
      <my-button></my-button>
    </div>
  </article>
  `;
}

@NgModule({
  imports: [
    DynamicHTMLModule.forRoot({
      components: [
        { component: MyButtonComponent, selector: 'my-button' },
      ]
    })
  ],
  declarations: [AppComponent, MyButtonComponent],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Result:

<my-app>
    <dynamic-html>
      <article>
        <h1>Awesome Document</h1>
        <div>
          <p>bla bla bla</p>
          <my-button>Click Me</my-button>
        </div>
      </article>
    </dynamic-html>
</my-app>

<my-button> is resolved as MyButtonComponent.

DynamicHTMLModule

To use <dynamic-html>, you have to import DynamicHTMLModule with forRoot static method. Its argument is a DynamicHTMLOptions object:

/**
 * defines dynamic-projectable components 
 * 
 * ```ts
 * @Component({
 *     selector: 'child-cmp',
 *     template: `<p>child:{{text}}</p>`,
 * })
 * 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<any>;
}

/**
 * options for DynamicHTMLModule
 */
export class DynamicHTMLOptions {
    /**
     * identifies components projected in dynamic HTML.
     */
    components: Array<ComponentWithSelector>;
}

OnMount Lifecycle method

/**
 * Lifecycle hook that is called after instantiation the component. 
 * This method is called before ngOnInit.
 */
export abstract class OnMount {
    abstract dynamicOnMount(attrs?: Map<string, string>, 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.

@Component({
  selector: 'awesome-button',
  template: `<button (click)="onClick()" #innerContent><ng-content></ng-content></button>`,
})
export class AwesomeButtonComponent implements OnMount, OnInit {
  @Input() msg: string;
  @ViewChild('innerContent') innerContent: ElementRef;

  dynamicOnMount(attr: Map<string, string>, 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');
  }
}

<dynamic-html> 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:

@Component({
  selector: 'dynamic-cmp-demo',
  template: `
    <div *dynamicComponent="template; context: {text: text};"></div>
  `,
})
export class DynamicCmpDemoComponent {
  template = `
  <article>
    <h1>Awesome Document</h1>
    <div>
      <p>{{text}}</p>
      <my-button></my-button>
    </div>
  </article>
  `;

  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:

<my-app>
    <ng-component>
      <article>
        <h1>Awesome Document</h1>
        <div>
          <p>foo</p>
          <my-button>Click Me</my-button>
        </div>
      </article>
    </ng-component>
</my-app>

<my-button> is resolved as MyButtonComponent.

DynamicComponentModule

To use dynamicComponent, you have to import DynamicComponentModule with forRoot static method. Its argument is a NgModule metadata object:

/**
 * 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!

More Repositories

1

contributors-img

Go
88
star
2

shiritori

Pull Requestでしりとりするだけのリポジトリです。
JavaScript
44
star
3

angular2-component-outlet

Angular2 dynamic component outlet
TypeScript
33
star
4

reactive-store

A store implementation for state management with RxJS
TypeScript
32
star
5

angular-testing-recipes

A collection of testing examples of Angular applications and libraries.
TypeScript
24
star
6

network-information-types

Type definitions for Network Information API
TypeScript
23
star
7

SmileEssence

Twitter client for android
Java
22
star
8

angular-modules-example

ng new -> new NgModule -> Lazy Loading
TypeScript
17
star
9

ngtools-webpack-example

example app using @ngtools/webpack
JavaScript
16
star
10

light-ts-loader

⚡ light weight & lightning fast TypeScript loader ⚡
TypeScript
15
star
11

angular-todomvc

TypeScript
15
star
12

ngx-web-bundles

[EXPERIMENTAL] Angular CLI builder for generate Web Bundle file (.wbn)
TypeScript
12
star
13

SmileEssence-Lite

twitter application for android
Java
12
star
14

ngx-grid-layout

monorepo for @lacolaco/* npm packages
TypeScript
11
star
15

c92-angular-pwa

TypeScript
10
star
16

angular-todo-example

Todo example with Angular
TypeScript
10
star
17

ngivy-playground

TypeScript
10
star
18

jsx-to-ivy-playground

TypeScript
10
star
19

angular2-testing-lite

Jasmine-free Angular 2 Testing Library
TypeScript
10
star
20

ng-router-scrolling-example

TypeScript
9
star
21

tsconfig-cli

CLI to resolve tsconfig.json
JavaScript
9
star
22

angular-comlink-example

https://blog.lacolaco.net/2018/12/enjoyable-webworkers-in-angular/
TypeScript
8
star
23

renovate-config

Opinionated Renovate config presets
8
star
24

angular-platform-server-example

https://github.com/laco0416/angular-platform-server-example/compare/09f832f...37956a0
TypeScript
8
star
25

zenn

https://zenn.dev/lacolaco のソースファイルを管理するリポジトリ
TypeScript
7
star
26

ngx-react

Use React elements with Angular
TypeScript
7
star
27

nx-angular-nest-docker-example

TypeScript
6
star
28

lacolaco_plugin

らこらこするプラグイン
Ruby
6
star
29

angular-jest-minimal

Example to use Jest for testing Angular CLI app
TypeScript
5
star
30

ng2-test-seed

TypeScript
5
star
31

ngivy-rx-subscribe-directive

AsyncPipe altenative
TypeScript
5
star
32

angular-redux-toolkit-playground

https://github.com/lacolaco/angular-redux-toolkit-playground/blob/master/src/app/app.store.ts
TypeScript
5
star
33

ng-operators

RxJS operators for Angular
TypeScript
5
star
34

angular-after-tutorial

https://github.com/lacolaco/zenn へ移管しました
5
star
35

angular-sac

Experiments of Stand-Alone Components
TypeScript
4
star
36

ngx-store

Please use @lacolaco/reactive-store instead.
TypeScript
4
star
37

gulp-tsconfig-update

A gulp plugin to update `files` property in tsconfig.json by `gulp.src`.
JavaScript
4
star
38

laco0416.github.io

HTML
4
star
39

ngrx-toh-example

Tour of Heroes with NgRx
TypeScript
4
star
40

angular-chartjs-dynamic-import

TypeScript
4
star
41

angular-tfjs-sandbox

TypeScript
4
star
42

feed2social

TypeScript
3
star
43

angular2-browserify-deps

Dependencies set for Angular2 with browserify
JavaScript
3
star
44

sw-lifecycle-sandbox

TypeScript
3
star
45

pcfg_js

PCFGのTypeScript実装
TypeScript
3
star
46

pokepartymatch

「パーティ構築したけど、あのポケモンの対策できてる?」を確認するためのツール
TypeScript
3
star
47

McLauncher2

マインクラフトのWindows用ランチャーアプリ
C#
3
star
48

angular-webbundle-example

TypeScript
3
star
49

angular-http-harness

Angular library for seamless migration from `$http` to `Http`
TypeScript
2
star
50

TokenCreator

Learning App: TypeScript + AngularJS + ASP.NET
TypeScript
2
star
51

angular-cypress-vistest-demo

HTML
2
star
52

blog.lacolaco.net

TypeScript
2
star
53

video-textify-devtools

JavaScript
2
star
54

gaego-ng2-skeleton

TypeScript
2
star
55

angular-architecture-playground01

Angular Architecture Playground 01
TypeScript
2
star
56

angular-eslint-flat-config

HTML
2
star
57

ngconf2017-notes

TypeScript
2
star
58

angular-dynamic-navlist-example

TypeScript
1
star
59

generator-chromeapp-dart

Yeoman generator for Chrome App in Dart http://yeoman.io
JavaScript
1
star
60

rtkquery-playground

TypeScript
1
star
61

gh-commits-changelog

Generate conventional-changelog from GitHub commits instead of raw git data
TypeScript
1
star
62

htnup.dart

Hatena blog entry uploader
Dart
1
star
63

cdk-testing-example

https://github.com/lacolaco/cdk-testing-example/blob/master/src/app/counter/counter.component.spec.ts
TypeScript
1
star
64

angular2-tour-of-heroes

Tour of Heroes with the latest API
TypeScript
1
star
65

lacolaco

1
star
66

akeome2015.dart

あけおめチャレンジ
Dart
1
star
67

MorseConverter

Morse converter for java
Java
1
star
68

ng-generate-lint-fix-example

Angular CLI 1.1.0 new feature. See commit logs
TypeScript
1
star
69

angular-typograms

TypeScript
1
star
70

angular-challenge-starter

HTML
1
star
71

learn-ng2-testing

JavaScript
1
star
72

htmlcomponent

TypeScript
1
star
73

angular-cdk-testing-sandbox

https://github.com/lacolaco/angular-cdk-testing-sandbox/blob/master/src/app/counter/counter.component.spec.ts
TypeScript
1
star
74

generator-gaego

Yeoman generator for GAE/Go
JavaScript
1
star
75

objective_regex

A dart library for generating regex pattern strings in an object-orient style
Dart
1
star
76

angular-service-worker-example

Example for @angular/service-worker (v5)
TypeScript
1
star