Saunak Nandi
Saunak Nandi

Reputation: 1

Is there a way to pass data between two same level component in Angular using @Input?

Folder structure of the project (for reference)

dynamic-container.component.html

<h1>Dynamic component in angular</h1>
<ul>
    <li (click)="createComponent(productNames.mobile)">Mobile</li>
    <li (click)="createComponent(productNames.laptop)">Laptop</li>
    <li (click)="createComponent(productNames.watch)">Watch</li>
    <li (click)="createComponent(productNames.burger)">Burger</li>
    <li (click)="createComponent(productNames.ovan)">Ovan</li>
</ul>

<div class="display black-border">
    <ng-container #container></ng-container>
</div>

dynamic-container.component.ts

@Component({
  selector: 'app-dynamic-container',
  templateUrl: './dynamic-container.component.html',
  styleUrls: ['./dynamic-container.component.css']
})
export class DynamicContainerComponent implements OnInit{
  @ViewChild('container',{read:ViewContainerRef,static:true}) container:ViewContainerRef|any
  
  componentMap=new Map<string,ComponentRef<any>>()
  index=0

  productNames:any={
    mobile:'mobile',
    laptop:'laptop',
    watch:'watch',
    burger:'burger',
    ovan:'ovan'
  }
  createComponent(name:string){

    const compType=this.getComponentType(name)
    const comp=this.container.createComponent(compType) // comp store the reference returned by the method

    let uniqueName=name+' - '+this.index.toString()
    this.index++
    comp.instance.name=uniqueName // comp has a instance property
  }

  getComponentType(name:string):Type<any>
  {
    let type: Type<any>=MobileComponent
    
    switch(name)
    {
      case this.productNames.mobile:{
        type=MobileComponent
        break
      }
      case this.productNames.laptop:{
        type=LaptopComponent
        break
      }
      case this.productNames.burger:{
        type=BurgerComponent
        break
      }
      case this.productNames.ovan:{
        type=OvanComponent
        break
      }
      case this.productNames.watch:{
        type=WatchComponent
        break
      }
    }
    return type
  }
}

Below dynamic-container you can see there is a component called mobile(refer the image).

In mobile.component.ts

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

@Component({
  selector: 'app-mobile',
  templateUrl: './mobile.component.html',
  styleUrls: ['./mobile.component.css']
})
export class MobileComponent {
  @Input() name:string=''
}

In mobile.component.html

<h4>{{name | titlecase}}</h4>

In case you want to see app.component.html

<app-dynamic-container></app-dynamic-container>

and app.module.ts

@NgModule({
    declarations: [
        AppComponent,
        DynamicContainerComponent,
        MobileComponent,
        LaptopComponent,
        BurgerComponent,
        WatchComponent,
        OvanComponent
    ],
    providers: [],
    bootstrap: [AppComponent],
    imports: [
        BrowserModule,
        CommonModule
    ],
    exports:[DynamicContainerComponent]
})
export class AppModule { }

I searched if there is any way of using @Input without property binding but found @Input need [property binding] and is done between parent and child component.

But you can see here it is done between 2 same level components that is dynamic-container and mobile.

So, I am not able to understand how it is happening under the hood or am I missing any concept. I found this in a youtube video here is the link - (https://www.youtube.com/watch?v=GE_lxrbFNtI&t=222s). Can anyone please help me understand this?

Upvotes: -2

Views: 247

Answers (1)

s_erfani
s_erfani

Reputation: 494

For passing data between same level component its better to use services. define your variables there and use it in both components. otherwise if you don't want to use services, first you need to share data between the child to parent using output and EventEmitter. Once received data in parent component share it to another child component using Input.

Upvotes: 1

Related Questions