当前位置: 首页 > 软件库 > Web应用开发 > Web框架 >

ng-dynamic-component

授权协议 MIT License
开发语言 JavaScript
所属分类 Web应用开发、 Web框架
软件类型 开源软件
地区 不详
投 递 者 戚成礼
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

ng-dynamic-component

Dynamic components with full life-cycle support for inputs and outputs

Angular ng-dynamic-component NPM package
11.x.x 8.x.x ng-dynamic-component@^8.0.0
10.x.x 7.x.x ng-dynamic-component@^7.0.0
9.x.x 6.x.x ng-dynamic-component@^6.0.0
8.x.x 5.x.x ng-dynamic-component@^5.0.0
7.x.x 4.x.x ng-dynamic-component@^4.0.0
6.x.x 3.x.x ng-dynamic-component@^3.0.0
5.x.x 2.x.x ng-dynamic-component@^2.0.0
4.x.x 1.x.x ng-dynamic-component@^1.0.0
2.x.x 0.x.x ng-dynamic-component@^0.0.0

Installation

$ npm install ng-dynamic-component --save

Error message in the IDE

If you have an error like Can't bind to 'ndcDynamicInputs' since it isn't a known property of 'ndc-dynamic' in your IDE, but the project compiles just fine, you might want to try installing the no-barrels version instead.

$ npm install --save ng-dynamic-component@no-barrels

Usage

DynamicComponent

Import DynamicModule where you need to render dynamic components:

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

@NgModule({
  imports: [DynamicModule],
})
export class MyModule {}

Then in your component's template include <ndc-dynamic> where you want to render componentand bind from your component class type of component to render:

@Component({
  selector: 'my-component',
  template: `
    <ndc-dynamic [ndcDynamicComponent]="component"></ndc-dynamic>
  `,
})
class MyComponent {
  component = Math.random() > 0.5 ? MyDynamicComponent1 : MyDynamicComponent2;
}

NgComponentOutlet

You can also use NgComponentOutletdirective from @angular/common instead of <ndc-dynamic>.

Import DynamicIoModule where you need to render dynamic inputs:

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

@NgModule({
  imports: [DynamicIoModule],
})
export class MyModule {}

Now apply ndcDynamicInputs and ndcDynamicOutputs to ngComponentOutlet:

@Component({
  selector: 'my-component',
  template: `<ng-template [ngComponentOutlet]="component"
                           [ndcDynamicInputs]="inputs"
                           [ndcDynamicOutputs]="outputs"
                           ></ng-template>`
})
class MyComponent {
  component = MyDynamicComponent1;
  inputs = {...};
  outputs = {...};
}

Also you can use ngComponentOutlet with * syntax:

@Component({
  selector: 'my-component',
  template: `<ng-container *ngComponentOutlet="component;
                            ndcDynamicInputs: inputs;
                            ndcDynamicOutputs: outputs"
                            ></ng-container>`
})
class MyComponent {
  component = MyDynamicComponent1;
  inputs = {...};
  outputs = {...};
}

Inputs and Outputs

You can pass inputs and outputs to your dynamic components:

Import module DynamicIoModule and then in template:

@Component({
  selector: 'my-component',
  template: `
    <ndc-dynamic
      [ndcDynamicComponent]="component"
      [ndcDynamicInputs]="inputs"
      [ndcDynamicOutputs]="outputs"
    ></ndc-dynamic>
  `,
})
class MyComponent {
  component = MyDynamicComponent1;
  inputs = {
    hello: 'world',
    something: () => 'can be really complex',
  };
  outputs = {
    onSomething: type => alert(type),
  };
}

@Component({
  selector: 'my-dynamic-component1',
  template: 'Dynamic Component 1',
})
class MyDynamicComponent1 {
  @Input()
  hello: string;
  @Input()
  something: Function;
  @Output()
  onSomething = new EventEmitter<string>();
}

Here you can update your inputs (ex. inputs.hello = 'WORLD') and they will trigger standard Angular's life-cycle hooks(of course you should consider which change detection strategy you are using).

Output template variables

Since v6.1.0

When you want to provide some values to your output handlers from template -you can do so by supplying a special object to your output that has shape {handler: fn, args: []}:

@Component({
  selector: 'my-component',
  template: `
    <ndc-dynamic
      [ndcDynamicComponent]="component"
      [ndcDynamicOutputs]="{
        onSomething: { handler: doSomething, args: ['$event', tplVar] }
      }"
    ></ndc-dynamic>
  `,
})
class MyComponent {
  component = MyDynamicComponent1;
  tplVar = 'some value';
  doSomething(event, tplValue) {}
}

Here you can specify at which argument event value should arrive via '$event' literal.

HINT: You can override event literal by providingEventArgumentToken in DI.

Component Creation Events

You can subscribe to component creation events, being passed a reference to the ComponentRef:

@Component({
  selector: 'my-component',
  template: `
    <ndc-dynamic
      [ndcDynamicComponent]="component"
      (ndcDynamicCreated)="componentCreated($event)"
    ></ndc-dynamic>
  `,
})
class MyComponent {
  component = MyDynamicComponent1;
  componentCreated(compRef: ComponentRef<any>) {
    // utilize compRef in some way ...
  }
}

Attributes

Since v2.2.0 you can now declaratively set attributes, as you would inputs, via ndcDynamicAttributes.

Import module DynamicAttributesModule and then in template:

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

@Component({
  selector: 'my-component',
  template: `
    <ndc-dynamic
      [ndcDynamicComponent]="component"
      [ndcDynamicAttributes]="attrs"
    ></ndc-dynamic>
  `,
})
class MyComponent {
  component = MyDynamicComponent1;
  attrs: AttributesMap = {
    'my-attribute': 'attribute-value',
    class: 'some classes',
  };
}

Remember that attributes values are always strings (while inputs can be any value).So to have better type safety you can use AttributesMap interface for your attributes maps.

Also you can use ngComponentOutlet and ndcDynamicAttributes with * syntax:

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

@Component({
  selector: 'my-component',
  template: `
    <ng-container
      *ngComponentOutlet="component; ndcDynamicAttributes: attrs"
    ></ng-container>
  `,
})
class MyComponent {
  component = MyDynamicComponent1;
  attrs: AttributesMap = {
    'my-attribute': 'attribute-value',
    class: 'some classes',
  };
}

Directives (experimental)

Since v3.1.0 you can now declaratively set directives, via ndcDynamicDirectives.

NOTE: In dynamic directives queries like @ContentChild and host decorators like @HostBindingwill not work due to involved complexity required to handle it (but PRs are welcome!).

Import module DynamicDirectivesModule and then in template:

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

@Component({
  selector: 'my-component',
  template: `
    <ng-container
      [ngComponentOutlet]="component"
      [ndcDynamicDirectives]="dirs"
    ></ng-container>
  `,
})
class MyComponent {
  component = MyDynamicComponent1;
  dirs = [dynamicDirectiveDef(MyDirective)];
}

It's also possible to bind inputs and outputs to every dynamic directive:

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

@Component({
  selector: 'my-component',
  template: `
    <ng-container
      [ngComponentOutlet]="component"
      [ndcDynamicDirectives]="dirs"
    ></ng-container>
  `,
})
class MyComponent {
  component = MyDynamicComponent1;
  directiveInputs = { prop1: 'value' };
  directiveOutputs = { output1: evt => this.doSomeStuff(evt) };
  dirs = [
    dynamicDirectiveDef(
      MyDirective,
      this.directiveInputs,
      this.directiveOutputs,
    ),
  ];
}

To change inputs, just update the object:

class MyComponent {
  updateDirectiveInput() {
    this.directiveInputs.prop1 = 'new value';
  }
}

You can have multiple directives applied to same dynamic component (only one directive by same type):

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

@Component({
  selector: 'my-component',
  template: `
    <ng-container
      [ngComponentOutlet]="component"
      [ndcDynamicDirectives]="dirs"
    ></ng-container>
  `,
})
class MyComponent {
  component = MyDynamicComponent1;
  dirs = [
    dynamicDirectiveDef(MyDirective1),
    dynamicDirectiveDef(MyDirective2),
    dynamicDirectiveDef(MyDirective3),
    dynamicDirectiveDef(MyDirective1), // This will be ignored because MyDirective1 already applied above
  ];
}

Extra

You can have more advanced stuff over your dynamically rendered components like setting custom injector ([ndcDynamicInjector])or providing additional/overriding providers ([ndcDynamicProviders]) or both simultaneouslyor projecting nodes ([ndcDynamicContent]).

NOTE: In practice functionality of this library is split in two pieces:

  • one - component (ndc-dynamic) that is responsible for instantiating and rendering of dynamic components;
  • two - directive (ndcDynamic also bound to ndc-dynamic) that is responsible for carrying inputs/outputsto/from dynamic component by the help of so calledDynamicComponentInjector.

Thanks to this separation you are able to connect inputs/outputs and life-cycle hooks to different mechanisms of injectingdynamic components by implementing DynamicComponentInjector and providing it viaDynamicComponentInjectorToken in DI.

It was done to be able to reuse NgComponentOutlet added in Angular 4-beta.3.

To see example of how to implement custom component injector - seeComponentOutletInjectorDirectivethat is used to integrate NgComponentOutlet directive with inputs/outputs.

License

MIT © Alex Malkevich

  • 作为angular应用的入口模块,了解他的重要性是显而易见的!今天闲来无事,便翻看@angular/platform-browser-dynamic源码,特此总结!希望观看过本篇文章对您有用! main.ts是这个样子的,下面我就去解开platformBrowserDynamic神秘面纱! import { platformBrowserDynamic } from 'iwe7/platform-

  • 异步数据加载 点击展开节点,动态加载数据,直到执行 addChildren() 方法取消加载状态。   import { Component } from '@angular/core'; import { NzFormatEmitEvent, NzTreeNode } from 'ng-zorro-antd'; @Component({ selector: 'nz-demo-tree-d

  • 动态组件 1、组件的模板不会永远是固定的。 2、应用可能会需要在运行期间加载一些新的组件。 3、展示如何使用ComponentFactoryResolver 来动态添加组件。 有两个场景 ——     eg1:假设正在计划一个广告活动,要在广告条中显示一系列不同的广告。几个不同的小组可能会频繁加入新的广告组件。     eg2:用户拖动相关的块到特定区域,区域中便会生成相应的UI控件,此UI控件有

  • 使用到动态组件是因为我在做一个Table的控件,表格中有按钮等控件,并具有相应逻辑,同时项目中多处使用到该表格,故想提取一个可复用的控件以减少工作量。主要参考的文章是大神的修仙之路Angular 4.x 动态创建组件以及官方文档Dynamic Component Loader; 这里主要简要记录一下我自己的理解。 动态组件的创建 在/src/app目录下通过以下命令可以创建一个简单的TestCom

  • 前言:   angular2相比angular1做了革命性的改变。对于开发者来说,我们知道它框架的实现上改变极大。我们看到代码也能发现它写法上变化很大,似乎完全是另一个东西。 但是当我们真正去写下去的时候,又会发现,处处都有angular1的影子,处处都是angular1的概念。对,没错。angular始终是angular,换件“衣服”,还是angular。 最开始我第一眼看到angular2的代

  • 更新: 2019-03-20  今天遇到烦人的情况, 在做 carousel 幻灯片插件.  <carousel> <item *ngFor="..." > <img lazyload ...> </item> <carousel> 本来是想用 ng-content 让外部的组件负责 for loop 然后把图放入到组件里.  后来发现要有 looping 的体验, 这样就需要

 相关资料
  • 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 Conten

  • NG Dynamic Forms NG Dynamic Forms is a rapid form development library based on the official Angulardynamic forms guide. It fully automates form UI creation by introducing a set of maintainable form co

  • WebAssembly enables load-time and run-time (dlopen) dynamic linking in the MVP by having multiple instantiated modules share functions, linear memories, tables and constants using module imports and e

  • 在动态数组类型的情况下,数组的初始长度为零。 必须使用标准SetLength函数设置数组的实际长度,该函数将分配用于存储数组元素的必要内存。 声明动态数组 要声明动态数组,请不要提及数组范围。 例如 - type darray = array of integer; var a: darray; 在使用数组之前,必须使用setlength函数声明大小 - setlength(a,

  • 动态模型定义具有dynamic segments的路由,Ember使用它来访问URL中的值。 动态段以:在route()方法中以:开头,后跟标识符。 必须使用模型中的id属性定义URL。 语法 (Syntax) Ember.Route.extend ({ model(params) { //code here } }); Router.map(function() {

  • 动态SQL是iBATIS的一个非常强大的功能。 有时您必须根据参数对象的状态更改WHERE子句标准。 在这种情况下,iBATIS提供了一组动态SQL标记,可以在映射语句中使用,以增强SQL的可重用性和灵活性。 使用一些额外的标签将所有逻辑放入.XML文件中。 以下是SELECT语句以两种方式工作的示例 - 如果您传递了ID,那么它将返回与该ID相对应的所有记录。 否则,它将返回员工ID设置为NUL