Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - @ViewChild from My Module

my question is regarding Angular 2/4/5 module.

Can't make @ViewChild work while using it from a module, the child is undefined. before I was using it as a simple component and it worked fine. *Tried @ViewChildren also... same

code samples -

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

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
}



}

When trying to search for an answer online only solution I found was to try @ViewChildren, or that it may happen cuz the view hasn't init yet. so I even tried to do it in a timeout of 5 seconds... same result. Again using the same code but as a simple app and not module worked fine.

Thanks for reading ! :)

like image 389
Ben Avatar asked Jul 18 '26 12:07

Ben


1 Answers

As I understood from the comments, you want to create a feature module for a component(s) and reuse it among your projects.

I suggest you take a look at this component library PrimeNg and their Github page. They have well-designed architecture, i.e. a feature module for a component.

Let's start from scratch and build our reusable component.

I created a new app with angular-cli

ng new my-proj

Then I created a feature module for a component I will develop later on. Let's call it MyComponent

ng generate module my-component

Then created a component with same name

ng generate component my-component

Then I edit MyComponent as following

my-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 ...
    }
}

Then I export it from my-component.module.ts as following

@NgModule({
    imports: [CommonModule],
    declarations: [MyComponentComponent],
    exports: [MyComponentComponent]
})
export class MyComponentModule { }

Then, imported this module in my app.module.ts and used this component in app.component

Also, if you want to access my-component within app.component, you can use 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();
    }
}

I hope this clarifies it for you

Edit

For publishing your library, you can check this article out:

Building an Angular 4 Component Library with the Angular CLI and ng-packagr

Also, for people who'll use your library to import your component and modules from same file, you can export it from your module as following

my-component.module.ts

export {MyComponentComponent} from './my-component.component.ts';

@NgModule({
    ...
})
export class MyComponentModule {}

To import it in your app.component,

app.component.ts

import {MyComponentComponent} from 'your-library/my-component.module';

You can import the module from same location

app.module.ts

import {MyComponentModule} from 'your-library/my-component.module';

like image 159
Bunyamin Coskuner Avatar answered Jul 20 '26 02:07

Bunyamin Coskuner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!