Angular - 来自我的模块的@ViewChild
Angular - @ViewChild from My Module
我的问题是关于 Angular 2/4/5 模块。
在模块中使用@ViewChild 时无法使它工作,子项未定义。在我将它用作一个简单的组件之前,它运行良好。
*也试过@ViewChildren...相同
代码示例 -
app.module.ts -
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MyNewModule} from './modules/MyNewModule/MyNewModule.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
MyNewModule,
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule { }
app.component.ts -
import { Component, OnInit } from '@angular/core';
import { MyNewModule} from './modules/MyNewModule/MyNewModule.module';
@Component({
selector: 'app-root',
template: `<button (click)="Print()">Print child</button>
<my-new-module></my-new-module>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
constructor(private MyModule:MyNewModule){}
ngOnInit(){}
Print(){
this.MyModule.Print();
}
}
modules/MyNewModule/MyNewModule.模块-
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MyNewModule} from './MyNewModule.component';
@NgModule({
imports: [
CommonModule,
],
declarations: [MyNewModule],
providers: [MyNewModule],
exports: [MyNewModule],
})
export class MyNewModule{ }
modules/MyNewModule/MyNewModule.ts-
import { Component, OnInit, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
@Component({
selector: 'my-new-module',
template:`<ng-template #Container></ng-template>`
})
export class MyNewModule implements OnInit {
@ViewChild('Container', {read: ViewContainerRef}) private container: ViewContainerRef;
constructor(){}
ngOnInit(){}
Print(){
console.log(this.container); => undefined
}
}
当尝试在线搜索答案时,我发现唯一的解决方案是尝试@ViewChildren,或者它可能会发生,因为视图尚未初始化。所以我什至尝试在 5 秒的超时时间内完成……同样的结果。
再次使用相同的代码,但作为一个简单的应用程序而不是模块工作正常。
感谢阅读! :)
您需要一个 ViewChild 来为您的模板引用 TemplateRef 和 ViewContainerRef。使用 ComponentResolverFactory
创建一个组件,然后使用组件 viewRef 创建一个嵌入视图。
@Component({
selector: 'widget',
template: '<ng-template #view></ng-template>'
})
export class WidgetComponent implements OnInit {
@ViewChild('view', { read: ViewContainerRef }) view: ViewContainerRef;
@ViewChild('view') template: TemplateRef<any>;
constructor(private factory: ComponentResolverFactory, private viewRef: ViewContainerRef) { }
ngOnInit() {
let component = ... some Type<any>...
let componentFactory = this.factory.resolveComponentFactory(component);
let ref:ComponentRef<any> = view.createComponent(componentFactory);
this.factory.create(this.view, this.message.component);
this.viewRef.createEmbeddedView(this.template);
}
}
正如我从评论中了解到的,您想为组件创建一个功能模块并在您的项目中重复使用它。
我建议你看看这个组件库 PrimeNg and their Github 页面。它们具有精心设计的架构,即组件的功能模块。
让我们从头开始构建我们的可重用组件。
我使用 angular-cli 创建了一个新应用
ng new my-proj
然后我为稍后开发的组件创建了一个功能模块。我们称它为 MyComponent
ng generate module my-component
然后创建了一个同名的组件
ng generate component my-component
然后我编辑MyComponent
如下
我的-component.component.ts
@Component({
selector: 'my-component',
template: `
<h1>My Component</h1>
<div #container>
<ng-content></ng-content>
</div>
`,
styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent implements OnInit, AfterContentInit {
@ViewChild('container') container: ElementRef;
constructor() { }
ngOnInit() {
console.log(this.container);
}
// this life cycle method is called after projected content is initialized.
ngAfterContentInit() {
console.log(this.container);
}
someMethod() {
// do something ...
}
}
然后我从 my-component.module.ts
导出它如下
@NgModule({
imports: [CommonModule],
declarations: [MyComponentComponent],
exports: [MyComponentComponent]
})
export class MyComponentModule { }
然后,在我的 app.module.ts
中导入了这个模块,并在 app.component
中使用了这个组件
此外,如果您想在 app.component
内访问 my-component
,您可以使用 ViewChild
app.component.ts
@Component({
selector: 'app-root',
template: `
<button (click)="onButtonClick()">Click me</button>
<my-component>
<div>This is from app component</div>
</my-component>
`,
})
export class AppComponent {
@ViewChild(MyComponentComponent) myComponent: MyComponentComponent;
onButtonClick() {
this.myComponent.someMethod();
}
}
我希望这能为你澄清
编辑
要发布您的图书馆,您可以查看这篇文章:
Building an Angular 4 Component Library with the Angular CLI and ng-packagr
此外,对于将使用您的库从同一文件导入您的组件和模块的人,您可以按以下方式从您的模块导出它
我的-component.module.ts
export {MyComponentComponent} from './my-component.component.ts';
@NgModule({
...
})
export class MyComponentModule {}
将其导入您的 app.component
、
app.component.ts
import {MyComponentComponent} from 'your-library/my-component.module'
;
您可以从同一位置导入模块
app.module.ts
import {MyComponentModule} from 'your-library/my-component.module';
我的问题是关于 Angular 2/4/5 模块。
在模块中使用@ViewChild 时无法使它工作,子项未定义。在我将它用作一个简单的组件之前,它运行良好。 *也试过@ViewChildren...相同
代码示例 -
app.module.ts -
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MyNewModule} from './modules/MyNewModule/MyNewModule.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
MyNewModule,
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule { }
app.component.ts -
import { Component, OnInit } from '@angular/core';
import { MyNewModule} from './modules/MyNewModule/MyNewModule.module';
@Component({
selector: 'app-root',
template: `<button (click)="Print()">Print child</button>
<my-new-module></my-new-module>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
constructor(private MyModule:MyNewModule){}
ngOnInit(){}
Print(){
this.MyModule.Print();
}
}
modules/MyNewModule/MyNewModule.模块-
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MyNewModule} from './MyNewModule.component';
@NgModule({
imports: [
CommonModule,
],
declarations: [MyNewModule],
providers: [MyNewModule],
exports: [MyNewModule],
})
export class MyNewModule{ }
modules/MyNewModule/MyNewModule.ts-
import { Component, OnInit, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
@Component({
selector: 'my-new-module',
template:`<ng-template #Container></ng-template>`
})
export class MyNewModule implements OnInit {
@ViewChild('Container', {read: ViewContainerRef}) private container: ViewContainerRef;
constructor(){}
ngOnInit(){}
Print(){
console.log(this.container); => undefined
}
}
当尝试在线搜索答案时,我发现唯一的解决方案是尝试@ViewChildren,或者它可能会发生,因为视图尚未初始化。所以我什至尝试在 5 秒的超时时间内完成……同样的结果。 再次使用相同的代码,但作为一个简单的应用程序而不是模块工作正常。
感谢阅读! :)
您需要一个 ViewChild 来为您的模板引用 TemplateRef 和 ViewContainerRef。使用 ComponentResolverFactory
创建一个组件,然后使用组件 viewRef 创建一个嵌入视图。
@Component({
selector: 'widget',
template: '<ng-template #view></ng-template>'
})
export class WidgetComponent implements OnInit {
@ViewChild('view', { read: ViewContainerRef }) view: ViewContainerRef;
@ViewChild('view') template: TemplateRef<any>;
constructor(private factory: ComponentResolverFactory, private viewRef: ViewContainerRef) { }
ngOnInit() {
let component = ... some Type<any>...
let componentFactory = this.factory.resolveComponentFactory(component);
let ref:ComponentRef<any> = view.createComponent(componentFactory);
this.factory.create(this.view, this.message.component);
this.viewRef.createEmbeddedView(this.template);
}
}
正如我从评论中了解到的,您想为组件创建一个功能模块并在您的项目中重复使用它。
我建议你看看这个组件库 PrimeNg and their Github 页面。它们具有精心设计的架构,即组件的功能模块。
让我们从头开始构建我们的可重用组件。
我使用 angular-cli 创建了一个新应用
ng new my-proj
然后我为稍后开发的组件创建了一个功能模块。我们称它为 MyComponent
ng generate module my-component
然后创建了一个同名的组件
ng generate component my-component
然后我编辑MyComponent
如下
我的-component.component.ts
@Component({
selector: 'my-component',
template: `
<h1>My Component</h1>
<div #container>
<ng-content></ng-content>
</div>
`,
styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent implements OnInit, AfterContentInit {
@ViewChild('container') container: ElementRef;
constructor() { }
ngOnInit() {
console.log(this.container);
}
// this life cycle method is called after projected content is initialized.
ngAfterContentInit() {
console.log(this.container);
}
someMethod() {
// do something ...
}
}
然后我从 my-component.module.ts
导出它如下
@NgModule({
imports: [CommonModule],
declarations: [MyComponentComponent],
exports: [MyComponentComponent]
})
export class MyComponentModule { }
然后,在我的 app.module.ts
中导入了这个模块,并在 app.component
此外,如果您想在 app.component
内访问 my-component
,您可以使用 ViewChild
app.component.ts
@Component({
selector: 'app-root',
template: `
<button (click)="onButtonClick()">Click me</button>
<my-component>
<div>This is from app component</div>
</my-component>
`,
})
export class AppComponent {
@ViewChild(MyComponentComponent) myComponent: MyComponentComponent;
onButtonClick() {
this.myComponent.someMethod();
}
}
我希望这能为你澄清
编辑
要发布您的图书馆,您可以查看这篇文章:
Building an Angular 4 Component Library with the Angular CLI and ng-packagr
此外,对于将使用您的库从同一文件导入您的组件和模块的人,您可以按以下方式从您的模块导出它
我的-component.module.ts
export {MyComponentComponent} from './my-component.component.ts';
@NgModule({
...
})
export class MyComponentModule {}
将其导入您的 app.component
、
app.component.ts
import {MyComponentComponent} from 'your-library/my-component.module'
;
您可以从同一位置导入模块
app.module.ts
import {MyComponentModule} from 'your-library/my-component.module';