GVKun编程网logo

angular – ng4 componentFactory将它放在DOM目标中(angular 嵌入html)

8

对于想了解angular–ng4componentFactory将它放在DOM目标中的读者,本文将提供新的信息,我们将详细介绍angular嵌入html,并且为您提供关于Angular2Compone

对于想了解angular – ng4 componentFactory将它放在DOM目标中的读者,本文将提供新的信息,我们将详细介绍angular 嵌入html,并且为您提供关于Angular 2 Components Communicate、Angular 2 Components(Angular 2 组件电子书教程免费下载)、Angular 2:如何在该Component中访问自定义Component的FormControl实例?、Angular 4:没有找到组件工厂,你是否将它添加到@ NgModule.entryComponents?的有价值信息。

本文目录一览:

angular – ng4 componentFactory将它放在DOM目标中(angular 嵌入html)

angular – ng4 componentFactory将它放在DOM目标中(angular 嵌入html)

我想做什么

我正在制作一个投票系统,它将在网站周围的多个组件中重复使用.为了保持干燥,我想从任何组件创建投票组件到指定的DOM元素.创建组件后,必须设置实例变量(在这种情况下模型:string和pk:number,都是公共的).

预期结果

我希望组件在指定位置呈现,打印在工厂创建组件后立即设置的正确数据.投票底部的输出应为Model:project PK:1

实际情况

ComponentFactory目前有两个由Component工厂创建的投票组件的输出:

>在正确的位置(目标div),但没有设置实例变量.

>在页面底部,但这是另一个问题,稍后和其他主题.

一些代码

@NgModule({
    ..
    declarations: [
        AppComponent,ProjectComponent,// parent for VoteContainer
        VoteComponent,// Dynamic component
    ],entryComponents: [
        VoteComponent,],..
})

包含VoteComponent工厂的父组件

export class ProjectDetailComponent implements AfterViewInit {
    @ViewChild('VoteComponentContainer',{read: ViewContainerRef}) VoteComponentContainer;

    public ngAfterViewInit() {
        this.factoryVoteComponent();
    }

    private factoryVoteComponent() {
        const VoteComponentFactory = this.componentFactoryResolver.resolveComponentFactory(VoteComponent);
        const VoteComponentRef = this.viewContainerRef.createComponent(VoteComponentFactory);
        VoteComponentRef.instance.model = "project";
        VoteComponentRef.instance.pk = 1;
        VoteComponentRef.changeDetectorRef.detectChanges();
    }
}

动态组件目标:

<Vote-component-container></Vote-component-container>

基本投票组件

@Component({
    selector: 'Vote-component-container',templateUrl: 'Vote.component.html',})

export class VoteComponent {
    public model:string;
    public pk:number;
    public constructor(){}
}

我试过了什么

我已经在这方面挣扎了很长一段时间,所以那里
是一些尝试让它工作.最后的尝试是
为工厂创建ViewChild.

除此之外,我一直在玩名称,设置组件模板接收器的不同方法等.

我想问的是什么

对于我现在正在尝试的情况,有没有人对动态组件的使用有任何经验?我希望在正确的方向上推动如何解决在正确的位置呈现的组件的问题,但没有可用的属性.

解决方法

经过一些研究,测试失败并尝试了更多 – 我发现它是一个解决方案.我还不是100%满意,因为它变得有点干燥和有组织 – 但是现在:

首先,我必须调整将数据传递给动态生成的组件的方式.我不得不更新我的选择器目标以接受所需的属性.在我的案例模型和objectId.

<Vote-component-container [model]="'project'" [objectId]="projectId"></Vote-component-container>

要将此数据链接到VoteComponent,VoteComponent本身需要@Input setter用于这些数据输入,例如:

import { Input,Component,AfterViewInit } from '@angular/core';

@Component({
    selector: 'Vote-component-container',})

export class VoteComponent implements AfterViewInit {
    // Temp public for testing
    public _objectId:number;
    public _model:string;

    public constructor(){}
    public ngAfterViewInit(){
        this.getVotes();
    }

    @Input('objectId')
    set objectId(objectId:number){
        this._objectId = objectId;
    }

    @Input('model')
    set model(model:string){
        this._model = model;
    }

    public getVotes(){
        ...
    }
}

并且最终在我的父组件中,我期望params [‘id’]部分是在ngAfterInit中调用函数的时候.但它没有,所以我不得不等待承诺..

@ViewChild('VoteComponentContainer',{read: ViewContainerRef}) target: ViewContainerRef;
private factoryVoteComponent(){
    this.activatedRoute.params.subscribe((params: Params) => {
        this.model = 'project';
        this.projectId = params['id'];

        let VoteComponentFactory = this.componentFactoryResolver.resolveComponentFactory(VoteComponent);
        this.VoteComponentRef = this.viewContainerRef.createComponent(VoteComponentFactory);
        this.VoteComponentRef.changeDetectorRef.detectChanges();
    });
}

Angular 2 Components Communicate

Angular 2 Components Communicate

本文介绍的内容是组件通信的常用方式:@Input、@Output、@ViewChild、模板变量、MessageService、Broadcaster (Angular 1.x $rootScope 中 $on、$broadcast ) 和 Pub - Sub 模式、RxJS Subject 存在的问题。

输入属性 (父组件 -> 子组件)

counter.component.ts

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

@Component({
    selector: ''exe-counter'',
    template: `
      <p>当前值: {{ count }}</p>
      <button (click)="increment()"> + </button>
      <button (click)="decrement()"> - </button>
    `
})
export class CounterComponent {
    @Input() count: number = 0;

    increment() {
        this.count++;
    }

    decrement() {
        this.count--;
    }
}

app.component.ts

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

@Component({
  selector: ''exe-app'',
  template: `
   <exe-counter [count]="initialCount"></exe-counter>
  `
})
export class AppComponent {
  initialCount: number = 5;
}

输出属性 (子组件 -> 父组件)

counter.component.ts

import { Component, Input, Output, EventEmitter } from ''@angular/core'';

@Component({
    selector: ''exe-counter'',
    template: `
      <p>当前值: {{ count }}</p>
      <button (click)="increment()"> + </button>
      <button (click)="decrement()"> - </button>
    `
})
export class CounterComponent {
    @Input() count: number = 0;

    @Output() change: EventEmitter<number> = new EventEmitter<number>();

    increment() {
        this.count++;
        this.change.emit(this.count);
    }

    decrement() {
        this.count--;
        this.change.emit(this.count);
    }
}

app.component.ts

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

@Component({
  selector: ''exe-app'',
  template: `
   <p>{{changeMsg}}</p> 
   <exe-counter [count]="initialCount" 
    (change)="countChange($event)"></exe-counter>
  `
})
export class AppComponent {
  initialCount: number = 5;

  changeMsg: string;

  countChange(event: number) {
    this.changeMsg = `子组件change事件已触发,当前值是: ${event}`;
  }
}

模板变量

child.component.ts

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

@Component({
  selector: ''child-component'',
  template: `I''m {{ name }}`
})

export class ChildComponent {
  public name: string;
}

parent.component.ts

import {Component, OnInit} from ''@angular/core'';
import {ChildComponent} from ''./child-component.ts'';

@Component({
  selector: ''parent-component'',
  template: `
    <child-component #child></child-component>
    <button (click)="child.name = childName">设置子组件名称</button>
  `
})

export class ParentComponent implements OnInit {
  
  private childName: string;
  
  constructor() { }

  ngOnInit() { 
    this.childName = ''child-component'';
  }
}

@ViewChild 装饰器

child.component.ts

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

@Component({
    selector: ''exe-child'',
    template: `
      <p>Child Component</p>  
    `
})
export class ChildComponent {
    name: string = '''';
}

app.component.ts

import { Component, ViewChild, AfterViewInit } from ''@angular/core'';
import { ChildComponent } from ''./child.component'';

@Component({
  selector: ''my-app'',
  template: `
    <h4>Welcome to Angular World</h4>
    <exe-child></exe-child>
  `,
})
export class AppComponent {

  @ViewChild(ChildComponent)
  childCmp: ChildComponent;

  ngAfterViewInit() {
    this.childCmp.name = ''child-component'';
  }
}

使用 MessageService - 基于 RxJS Subject

message.service.ts

import { Injectable } from ''@angular/core'';
import {Observable} from ''rxjs/Observable'';
import { Subject } from ''rxjs/Subject'';

@Injectable()
export class MessageService {
    private subject = new Subject<any>();

    sendMessage(message: string) {
        this.subject.next({ text: message });
    }

    clearMessage() {
        this.subject.next();
    }

    getMessage(): Observable<any> {
        return this.subject.asObservable();
    }
}

home.component.ts

import { Component } from ''@angular/core'';
import { MessageService } from ''./message.service'';

@Component({
    selector: ''exe-home'',
    template: `
    <div>
        <h1>Home</h1>
        <button (click)="sendMessage()">Send Message</button>
        <button (click)="clearMessage()">Clear Message</button>
    </div>`
})

export class HomeComponent {
    constructor(private messageService: MessageService) {}
    
    sendMessage(): void {
        this.messageService.sendMessage(''Message from Home Component to App Component!'');
    }

    clearMessage(): void {
        this.messageService.clearMessage();
    }
}

app.component.ts

import { Component, OnDestroy } from ''@angular/core'';
import { Subscription } from ''rxjs/Subscription'';
import { MessageService } from ''./message.service'';

@Component({
    selector: ''my-app'',
    template: `
    <div>
       <div *ngIf="message">{{message.text}}</div>
       <exe-home></exe-home>
    </div>
    `
})

export class AppComponent implements OnDestroy {
    message: any;
    subscription: Subscription;

    constructor(private messageService: MessageService) {
        this.subscription = this.messageService
                                  .getMessage().subscribe( message => { 
                                      this.message = message; 
                                 });
    }

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
}

使用 Broadcaster - 基于 RxJS Subject

实现 Angular 1.x 中的 $rootScope 对象中 $on$broadcast 的功能。

broadcaster.ts

import { Injectable } from ''@angular/core'';
import {Subject} from ''rxjs/Subject'';
import {Observable} from ''rxjs/Observable'';
import ''rxjs/add/operator/filter'';
import ''rxjs/add/operator/map'';

interface BroadcastEvent {
  key: any;
  data?: any;
}

@Injectable()
export class Broadcaster {
  private _eventBus: Subject<BroadcastEvent>;

  constructor() {
    this._eventBus = new Subject<BroadcastEvent>();
  }

  broadcast(key: any, data?: any) {
    this._eventBus.next({key, data});
  }

  on<T>(key: any): Observable<T> {
    return this._eventBus.asObservable()
      .filter(event => event.key === key)
      .map(event => <T>event.data);
  }
}

child.component.ts

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

@Component({
    selector: ''child''
})
export class ChildComponent {
  constructor(private broadcaster: Broadcaster) {}
  
  registerStringBroadcast() {
    this.broadcaster.on<string>(''MyEvent'')
      .subscribe(message => {
        ...
      });
  }

  emitStringBroadcast() {
    this.broadcaster.broadcast(''MyEvent'', ''some message'');
  }
}

本文主要是介绍组件通讯的思路,提供的都是相对简单的示例。如果想深入了解,请参考 - angular.cn - component-communication。

我有话说

1.在实际开发中,我们也经常使用 Pub (发布) - Sub (订阅模式) 来实现模块之间的消息通讯。接下来我们看一下 Pub - Sub 的核心点:

  • 至少包含 subscribe() 和 publish() 两个方法,subscribe() 用于实现消息订阅,publish() 方法用于发布消息。

  • 支持订阅不同的消息类型,且对于任何一种消息类型都可以添加多个观察者。内部实现一般使用 key-value 结构进行消息类型和观察者列表的存储。

  • 订阅观察者后,最好返回一个对象或函数对象,用于取消订阅。

具体示例如下(详细信息,请参考 - Pub/Sub JavaScript Object):

var events = (function(){
  var topics = {};
  var hOP = topics.hasOwnProperty;

  return {
    subscribe: function(topic, listener) {
      // 如果topic类型不存在,则创建
      if(!hOP.call(topics, topic)) topics[topic] = [];
      
      // 添加listener
      var index = topics[topic].push(listener) -1;

      // 返回对象用于移除listener
      return {
        remove: function() {
          delete topics[topic][index];
        }
      };
    },
    publish: function(topic, info) {
      if(!hOP.call(topics, topic)) return;

      topics[topic].forEach(function(item) {
              item(info != undefined ? info : {});
      });
    }
  };
})();

使用示例:

var subscription = events.subscribe(''/page/load'', function(obj) {
    // 事件处理
});

events.publish(''/page/load'', {
    url: ''/some/url/path'' 
});

2.RxJS Subject 在使用中存在一个问题,就是如果某个 observer (观察者) 在执行的时候出现异常,却没有进行异常处理,那么就会影响到其它的观察者。解决该问题,最简单的方式就是为所有的观察者添加异常处理。具体问题如下:

const source = Rx.Observable.interval(1000);
const subject = new Rx.Subject();

const example = subject.map(x => {
    if (x === 1) {
        throw new Error(''oops'');
    }
    return x;
});
subject.subscribe(x => console.log(''A'', x));
example.subscribe(x => console.log(''B'', x));
subject.subscribe(x => console.log(''C'', x));

source.subscribe(subject);

以上代码运行后,控制台的输出结果:

A 0
B 0
C 0
A 1
Rx.min.js:74 Uncaught Error: oops

解决方案:

const source = Rx.Observable.interval(1000);
const subject = new Rx.Subject();

const example = subject.map(x => {
    if (x === 1) {
        throw new Error(''oops'');
    }
    return x;
});

subject.subscribe(
    x => console.log(''A'', x),
    error => console.log(''A Error:'' + error)
);
    
example.subscribe(
    x => console.log(''B'', x),
    error => console.log(''B Error:'' + error)
);

subject.subscribe(
    x => console.log(''C'', x),
    error => console.log(''C Error:'' + error)
);

source.subscribe(subject);

关于 RxJS Subject 的详细信息,请查看 - RxJS Subject。

Angular 2 Components(Angular 2 组件电子书教程免费下载)

Angular 2 Components(Angular 2 组件电子书教程免费下载)

Angular 2 组件电子书教程

下载地址:AngularJS Directives Cookbook.pdf

更多Angular电子书、React电子书、Vue.js电子书,请关注我的简书主页。

Angular 2:如何在该Component中访问自定义Component的FormControl实例?

Angular 2:如何在该Component中访问自定义Component的FormControl实例?

所以我一直在阅读如何在Angular2中构建自定义FormControls,但我无法得到我正在努力完成验证的工作.我有一个正常的输入控件,我想在自定义组件中包装,以便我可以这样做:

<my-control name="something" [(ngModel)]="model.something" required></my-control>

而不是每次都重复这个:

<divhttps://www.jb51.cc/tag/Feed/" target="_blank">Feedback" [ngClass]="{'has-success': someInput.valid,'has-error': someInput.invalid && someInput.dirty}">
    <labelfor="someId">{{label || 'Some Input'}}</label>
    <input type="test"id="someId" placeholder="Some Input" [ngModel]="value" (ngModel)="onChange($event)" name="someInput" required #someInput="ngModel" minlength="8"/>
    <spanhttps://www.jb51.cc/tag/Feed/" target="_blank">Feedback" aria-hidden="true" [ngClass]="{'glyphicon-ok': someInput.valid,'glyphicon-remove': someInput.invalid && someInput.dirty}"></span>
    <div [hidden]="someInput.valid || someInput.pristine || !someInput.errors.required">Some Input is required</div>
    <div [hidden]="someInput.valid || someInput.pristine || !someInput.errors.minlength">Some Input must be at least 8 characters</div>
</div>

所以我通过自定义组件实现了以下有关如何在线创建自定义组件的文章:

https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

缺少的是能够将验证移出组件,但允许自定义组件处理该验证的显示.因此,如果你看一下我的目的是允许组件的用户指定验证而不是让组件强加特定的验证(注意某些验证是组件固有的,例如电子邮件地址组件会验证它是一封没有用户指定的电子邮件).请注意,必需的是该客户组件的使用情况.

那么如何在该组件的定义中获得对自定义组件的FormControl的引用?注意:我理解如何访问模板的FormControl实例中的输入字段,因为上面的代码完全证明了这一点.我要求的是模板所在的自定义控件的FormControl实例.在我引用的文章中,它将是CounterInputComponent的FormControl.

解决方法

添加这似乎工作:

@ViewChild(NgModel) model: NgModel;

然后你可以通过以下方式访问FormControl:

this.model.control

Angular 4:没有找到组件工厂,你是否将它添加到@ NgModule.entryComponents?

Angular 4:没有找到组件工厂,你是否将它添加到@ NgModule.entryComponents?

我正在使用带有webpack的Angular 4模板
当我尝试使用组件(ConfirmComponent)时出现此错误:

No component factory found for ConfirmComponent. Did you add it to
@NgModule.entryComponents?

组件在app.module.server.ts中声明

NgModule({
    bootstrap: [ AppComponent ],imports: [
     ...
    ],entryComponents: [
        ConfirmComponent,],})
export class AppModule {
}

我还有app.module.browser.ts和app.module.shared.ts

如何解决这个问题。
谢谢

在你的module.ts中添加这个,
declarations: [
     AppComponent,ConfirmComponent
  ]

如果ConfirmComponent在另一个模块中,你需要将它导出到那里,这样你可以在外面使用它,添加:

exports: [ ConfirmComponent ]

今天关于angular – ng4 componentFactory将它放在DOM目标中angular 嵌入html的分享就到这里,希望大家有所收获,若想了解更多关于Angular 2 Components Communicate、Angular 2 Components(Angular 2 组件电子书教程免费下载)、Angular 2:如何在该Component中访问自定义Component的FormControl实例?、Angular 4:没有找到组件工厂,你是否将它添加到@ NgModule.entryComponents?等相关知识,可以在本站进行查询。

本文标签: