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

huangapple go评论60阅读模式
英文:

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

问题

项目的文件结构(供参考)

dynamic-container.component.html

<h1>Angular中的动态组件</h1>
<ul>
    <li (click)="createComponent(productNames.mobile)">手机</li>
    <li (click)="createComponent(productNames.laptop)">笔记本电脑</li>
    <li (click)="createComponent(productNames.watch)">手表</li>
    <li (click)="createComponent(productNames.burger)">汉堡包</li>
    <li (click)="createComponent(productNames.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: '手机',
    laptop: '笔记本电脑',
    watch: '手表',
    burger: '汉堡包',
    ovan: '烤箱'
  };

  createComponent(name: string) {
    const compType = this.getComponentType(name);
    const comp = this.container.createComponent(compType);
    
    let uniqueName = name + ' - ' + this.index.toString();
    this.index++;
    comp.instance.name = uniqueName;
  }

  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;
  }
}

在dynamic-container下面,你可以看到一个名为mobile的组件(参考图片)。

在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 = '';
}

在mobile.component.html中

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

如果你想看app.component.html

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

app.module.ts

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

我搜索了一下,是否有一种在没有属性绑定的情况下使用@Input的方法,但发现@Input需要**[属性绑定]**,通常在父子组件之间进行。

但你可以看到这里是在两个同级组件之间进行的,即dynamic-container和mobile

所以,我无法理解它是如何在底层发生的,或者我是否遗漏了某个概念。我在YouTube上找到了这个视频,这是链接 - (https://www.youtube.com/watch?v=GE_lxrbFNtI&amp;t=222s)。有人可以帮助我理解吗?

英文:

Folder structure of the project (for reference)

dynamic-container.component.html

&lt;h1&gt;Dynamic component in angular&lt;/h1&gt;
&lt;ul&gt;
&lt;li (click)=&quot;createComponent(productNames.mobile)&quot;&gt;Mobile&lt;/li&gt;
&lt;li (click)=&quot;createComponent(productNames.laptop)&quot;&gt;Laptop&lt;/li&gt;
&lt;li (click)=&quot;createComponent(productNames.watch)&quot;&gt;Watch&lt;/li&gt;
&lt;li (click)=&quot;createComponent(productNames.burger)&quot;&gt;Burger&lt;/li&gt;
&lt;li (click)=&quot;createComponent(productNames.ovan)&quot;&gt;Ovan&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;display black-border&quot;&gt;
&lt;ng-container #container&gt;&lt;/ng-container&gt;
&lt;/div&gt;

dynamic-container.component.ts

@Component({
selector: &#39;app-dynamic-container&#39;,
templateUrl: &#39;./dynamic-container.component.html&#39;,
styleUrls: [&#39;./dynamic-container.component.css&#39;]
})
export class DynamicContainerComponent implements OnInit{
@ViewChild(&#39;container&#39;,{read:ViewContainerRef,static:true}) container:ViewContainerRef|any
componentMap=new Map&lt;string,ComponentRef&lt;any&gt;&gt;()
index=0
productNames:any={
mobile:&#39;mobile&#39;,
laptop:&#39;laptop&#39;,
watch:&#39;watch&#39;,
burger:&#39;burger&#39;,
ovan:&#39;ovan&#39;
}
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+&#39; - &#39;+this.index.toString()
this.index++
comp.instance.name=uniqueName // comp has a instance property
}
getComponentType(name:string):Type&lt;any&gt;
{
let type: Type&lt;any&gt;=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 &#39;@angular/core&#39;;
@Component({
selector: &#39;app-mobile&#39;,
templateUrl: &#39;./mobile.component.html&#39;,
styleUrls: [&#39;./mobile.component.css&#39;]
})
export class MobileComponent {
@Input() name:string=&#39;&#39;
}

In mobile.component.html

&lt;h4&gt;{{name | titlecase}}&lt;/h4&gt;

In case you want to see app.component.html

&lt;app-dynamic-container&gt;&lt;/app-dynamic-container&gt;

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&amp;t=222s).
Can anyone please help me understand this?

答案1

得分: 1

使用services在同级组件之间传递数据更好。在那里定义您的变量,然后在两个组件中使用它。
否则,如果您不想使用服务,首先需要使用outputEventEmitter在子组件和父组件之间共享数据。一旦在父组件中接收到数据,再将其分享给另一个子组件,使用Input

英文:

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.

huangapple
  • 本文由 发表于 2023年5月14日 15:53:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76246413.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定