Search code examples
angulartypescriptangular7angular-components

Angular7 - Inject Component in another Component


Is it correct inject Component in another Component to access functions or properties in injected Component?
Notice: None of these components is a child of another

import { UsersComponent } from './../users/users.component';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  constructor(users:UsersComponent){
    users.getAllUsers()
  }
}

Solution

  • You can't actually do it this way. In Angular, we think everything as a component wise. If any method or property is used by multiple component you can follow below methods. As your components are not related as child parent. you can follow 3 and 4 Methods.

    1. Parent to Child and Child to Parent: Sharing Data via @Input and @Output

    This is most frequently used way of sharing data between components. It uses @Input() decorator. You can also use @Output() decorator to event pass to the parent.

    parent.component.ts:

    @Component({
      selector: 'app-parent',
      template: `
        <p>{{ message }}</p>
        <app-child [input]="parentData" (output)="childMsg($event)"></app-child>`
    })
    export class ParentComponent{
      message: string;
      parentData = "message from parent"
      childMsg(event) {
        this.message = event;
      }
    }
    

    child.component.ts:

    @Component({
      selector: 'app-child',
      template: `
        <p>{{ input }}</p>
        <button (click)="submit()">Submit</button>
      `
    })
    export class ChildComponent {
    
      @Input() input: string;
      @Output() output = new EventEmitter<string>();
      message: string = "Hello World!"
      submit() {
        this.output.emit(this.message)
      }
    }
    

    2. Child to Parent: Sharing Data via ViewChild

    @ViewChild decorator allows a one component to be injected into another, giving the parent access to its properties and methods.

    parent.component.ts

    @Component({
      selector: 'app-parent',
      template: `
        Message: {{ childData }}
        <app-child></app-child>
      `,
      styleUrls: ['./parent.component.css']
    })
    export class ParentComponent implements AfterViewInit {
    
      @ViewChild(ChildComponent) child;    
    
      childData: string;
    
      ngAfterViewInit() {
        this.childData = this.child.message
      }
    }
    

    child.component.ts:

    @Component({
      selector: 'app-child',
    })
    export class ChildComponent {
    
      childData = 'Hola Mundo!';
    
    }
    

    N.B: we use AfterViewInit lifeCycle because the child wasn't available until the view is initialized.

    3. Unrelated Components using Service: Sharing Data between unrelated components with a Service and Behavior Subject

    common.service.ts:

    @Injectable()
    export class CommonService {
      private data = new BehaviorSubject('default data');
      data$ = this.data.asObservable();
    
      changeData(data: string) {
        this.data.next(data)
      }
    }
    

    component-one.component.ts:

    @Component({
      selector: 'app-component-one',
      template: `<p>{{data}}</p>`
    })
    export class ComponentOneComponent implements OnInit {
    
      data: string;
    
      constructor(private service: CommonService) { }
    
      ngOnInit() {
        this.service.data$.subscribe(res => this.data = res)
      }
    
    }
    

    component-two.component.ts:

    @Component({
      selector: 'app-component-two',
      template: `
        <p>{{data}}</p>
        <button (click)="newData()">Next Data</button>`
    })
    export class ComponentTwoComponent implements OnInit {
    
      data: string;
    
      constructor(private service: CommonService) { }
    
      ngOnInit() {
        this.service.data$.subscribe(res => this.data = res)
      }
      newData() {
        this.service.data.next('Changed Data');
      }
    }
    

    4. State Management: Share data between unrelated components using NgRx You can use store like NgRx to manage state where you will store your property then use everywhere. Example I followed this example when learning ngrx.