简体   繁体   English

Angular 5 - 从另一个组件更改变量

[英]Angular 5 - change variable from another Component

I have a ParentComponent with a ChildComponent that contains another ChildComponent ( ResultList in a sidebar)我有一个带有ChildComponentParentComponent ,其中包含另一个ChildComponent (侧栏中的ResultList

In the ParentComponent I open a dialog with a similar ResultList from the sidebar- technically it is the same component - but it has more items.I try to select some of the values in the dialog and then I want to push them to the first ResultList in the sidebar again.ParentComponent我从侧边栏中打开一个带有类似ResultList的对话框——从技术上讲,它是同一个组件——但它有更多的项目。我尝试在对话框中选择一些值,然后我想将它们推送到第一个ResultList再次在侧边栏中。

Now I'm trying to pass the resultList variable to each component to get my list updated in the sidebar, but it seems a little bit complex.现在我正在尝试将resultList变量传递给每个组件,以便在侧边栏中更新我的列表,但这似乎有点复杂。

If you (hopefully) unterstand my problem - Do you have any other ideas how can I update my sidebarcomponent from the modal dialog?如果您(希望)理解我的问题 - 您还有其他想法如何从模态对话框更新我的侧边栏组件?

If you have further questions - please ask :)如果您有其他问题 - 请询问:)

I'd recommend using a Service with a BehaviorSubject exposed asObservable and subscribe ing to it in all the components where you want to get the updated resultList 我建议使用将BehaviorSubject公开为asObservableService ,并在要获取更新的resultList所有组件中subscriberesultList

So you'll have a service: 因此,您将获得服务:

import { BehaviorSubject, Observable } from 'rxjs';
...
export class ResultListService {
  private resultList: BehaviorSubject<any[]> = new BehaviorSubject<any[]>(null);
  public resultList$: Observable<any[]> = this.resultList.asObservable();

  updateResultList(updatedList) {
    this.resultList.next(updatedList);
  }
}

In the dialog component, you'll use the updateResultList method and pass it the updatedResultList: 在对话框组件中,您将使用updateResultList方法,并将updateResultList方法传递给它:

constructor(..., private resultListService: ResultListService) {}
...
this.resultListService.updateResultList(updatedResultList);

Now in any component where you want the updated resultList , just subscribe to resultList$ from ResultListService : 现在,在您想要更新的resultList任何组件中,只需从ResultListService subscribe resultList$

constructor(..., private resultListService: ResultListService) {}
...
this.resultListService.resultList$
  .subscribe(resultList => console.log('This is the updated resultList: ', resultList));

There are other options besides chaining @Input and @Output parameters through multiple components or using a service (which is likely the best solution if you are new to Angular), one of which is making use of shared state. 除了通过多个组件或使用服务来链接@Input和@Output参数之外,还有其他选择(如果您是Angular的新手,这可能是最佳解决方案),其中之一是利用共享状态。

Using a state management framework such ngrx , ngxs or akita allows you to share both state and changes to that state between components - in this case arrays and changes to their content. 使用诸如ngrxngxsakita之类的状态管理框架,您可以在组件之间共享状态和对该状态的更改-在这种情况下,是数组及其内容的更改。

Once set up the store would manage adding the items selected in your child component to the array referenced in the parent component. 设置完成后,商店将设法将在子组件中选择的项目添加到父组件中引用的数组中。 The two components would not even have to be related to each other. 这两个组成部分甚至不必相互关联。

These two tutorials for ngrx and ngxs both cover a use case similar to yours. 这两个有关ngrxngxs的教程都涵盖了与您相似的用例。 The fact that you are using a modal dialog and two lists does not change anything in regards to how the store is used. 您正在使用模式对话框和两个列表的事实不会改变商店的使用方式。

This is likely out of scope for what you are trying to accomplish but something you could keep in mind. 对于您要完成的工作,这可能超出范围,但您需要牢记。

If you want to share a value between components, you should do a Service that will be injected in each component where you need it. 如果要在组件之间共享值,则应执行一项服务 ,该服务将注入到需要的每个组件中。

@Injectable({
 providedIn: 'root',
})
export class ResultListService {
  public myResultList: string;
}

(With the providedIn: 'root' , it will be injected at the root of your app so it will be instancied only one time and the same instance will be shared among components) (使用providedIn: 'root' ,它将注入到应用程序的根目录,因此只能实例化一次,并且在组件之间共享同一实例)

Then you pass it in the constructor parameters of your componenents: 然后,将其传递到组件的构造函数参数中:

export class SidebarComponent   {

  constructor(public resultListService: ResultListService){}

  // this.resultListService.myResultList
}

Component A- HTML组件 A- HTML

<button (click) = "changeFoo()">Change Value</button>

Component A- Typpescript组件 A - 打字稿

    import { SharedService } from './../../shared.service';
constructor(private sharedService: SharedService) {}

Component B-Html组件 B-Html

<div style="margin:0; padding:0">
            {{xIsANumberVal == null? '' : "Value Passed From A Component 
            Comp(Parent): "+xIsANumberVal }}
</div>

Component B- Typescript组件 B- 打字稿

import { SharedService } from './../../shared.service';
 xIsANumberVal!: number;
constructor(
    private sharedService: SharedService
  ) {}

ngOnInit() {
    this.receiveValueFromService();
  }

    receiveValueFromService() {
        this.sharedService.valueSource.subscribe(value => {
          this.xIsANumberVal = value;
        });
      }

Shared Service共享服务

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SharedService {

  xIsANumberVal: number = 5;
  valueSource: Subject<number> = new Subject();


  get abc(): Subject<number> {
    return this.valueSource;
  }

  constructor() { }


  changeFoo(xIsANumberVal: number) {
    this.valueSource.next(xIsANumberVal);
  }
}

Working Example: https://stackblitz.com/edit/github-u6xvad?file=src%2Fapp%2Fsecond%2Fsecond.component.ts工作示例: https : //stackblitz.com/edit/github-u6xvad?file=src%2Fapp%2Fsecond%2Fsecond.component.ts

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM