如何根据Angular中一个组件中的click事件更改其他组件中的数据?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何根据Angular中一个组件中的click事件更改其他组件中的数据?相关的知识,希望对你有一定的参考价值。

我是Angular的初学者,我开发了一个Angular 4/5应用程序,由5个组件组成:A,B,C,D和E.所有这些组件都显示在单个(相同)页面上。组件A由导航栏中的下拉列表组成。现在,我要做的是,在组件A的下拉列表中选择任何特定选项后,我将同时更改其他组件B,C,D和E的数据。

我非常困惑如何实现这种数据绑定。任何人都可以帮助如何实现这一目标?

由于发布整个代码将是一项非常困难的任务,因为我有大约2打文件,所以我发布了组件A,组件B和根组件的代码。

组件A代码,其中组件A是导航栏

导航bar.component.html

<div class="container model-family-navigation-bar">
  <nav class="navbar navbar-expand-sm navbar-dark model-family-navigation-bar">
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
      aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav">
        <!-- <div class="col-sm-auto"> -->
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle navigation-bar-content text-white" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
            aria-haspopup="true" aria-expanded="false">
            <span id="selected">Model Family</span>
          </a>
          <div class="dropdown-menu bg-success table-striped" aria-labelledby="navbarDropdown">
            <h1 class="dropdown-header text-white">Select Model Family</h1>
            <div *ngFor="let item of dropdownElements">
              <div class="dropdown-divider"></div>
              <a class="dropdown-item" (click)="showList()">{{item.model_family}}</a>
            </div>
          </div>
        </li>
        <!-- </div> -->
        <!-- <div class="col-sm-auto"> -->
        <li class="nav-item">
          <span class="navigation-bar-content navbar-text text-white ml-4">Proportional Directional Valve</span>
        </li>
        <!-- </div> -->
      </ul>

      <ul class="navbar-nav ml-auto">
        <li class="nav-item navbar-right">
          <a class="nav-link text-white" href="https://www.google.com/">Data Sheet</a>
        </li>
      </ul>

    </div>
  </nav>
</div>

导航bar.component.ts:

import { Component, OnInit } from '@angular/core';
import {NavigationDropdownElements} from './navigation-bar-dropdownElements'

@Component({
  selector: 'navigation-bar',
  templateUrl: './navigation-bar.component.html',
  styleUrls: ['./navigation-bar.component.css']
})
export class NavigationBarComponent implements OnInit {
  dropdownElements = NavigationDropdownElements;

  ngOnInit() {}

}

导航栏,dropdownElements.ts

class NavigationDropdown{
    model_family: string;
}
export const NavigationDropdownElements: NavigationDropdown[] = [
    { model_family: 'CP210-1'},
    { model_family: 'CP211-2'},
    { model_family: 'CP212-3'}
];

组件B代码,其中组件B是模型族描述

模型家庭description.component.ts:

import { Component, OnInit } from '@angular/core';
import { descriptionElements1, descriptionElements2 } from './model-family-description-elements';
@Component({
  selector: 'model-family-description',
  templateUrl: './model-family-description.component.html',
  styleUrls: ['./model-family-description.component.css']
})
export class ModelFamilyDescriptionComponent implements OnInit {
  desc1 = descriptionElements1;
  desc2 = descriptionElements2;
  constructor() { }

  ngOnInit() {
  }

}

模型家庭description.component.html

<div class="container border-section">
  <div class="row">
    <p class="ml-2">{{desc2.description}}</p>
  </div>
</div>

模型家族的描述,elements.ts

class ModelFamilyDescription {
    description: string;
}

export const descriptionElements1: ModelFamilyDescription =
    { description: 'This is a proportional, 3 position 4 way, directional control valve.' };

export const descriptionElements2: ModelFamilyDescription =
    { description: 'This is a proportional, 4 position 5 way, non-directional control valve.' };

根组件:

app.component.html:

<navigation-bar></navigation-bar>
<model-family-description></model-family-description>

app.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

}

请帮忙。

答案

你应该用@Injectable创建一个共同的Subject

例:

@Injectable()
export class CommonService {

    private dropdownValue: Subject<string> = new Subject();

    public getDropdownValue() : Observable {
        return this.dropdownValue.asObservable();
    }

    public setDropdownValue(value: string) : void {
        this.dropdownValue.next(value);
    }

然后在组件A中:

constructor(
    private commonService: CommonService
) {
   ...
}

protected onDropdownChange(value: string) : void {
    this.commonService.setDropdownValue(value);
}        

在其他组件中:

constructor(
    private commonService: CommonService
) {
    this.commonService.getDropdownValue().subscribe((newValue) => {
        // action on data change
    });
}
另一答案

首先创建一个服务:

例如:

message.service.ts

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

@Injectable()
export class MessageService {
    private subject = new Subject<any>();

    sendMessage(message: string) {
        this.subject.next({ text: message });
    }

    clearMessage() {
        this.subject.next();
    }

    getMessage(): Observable<any> {
        return this.subject.asObservable();
    }
}

然后将该服务添加到app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

import { MessageService } from './message.service';

@NgModule({
  imports:      [
    BrowserModule,
    FormsModule,
    ModalModule.forRoot()
  ],
  declarations: [
    AppComponent 
  ],
  providers:    [
    MessageService
  ],
  bootstrap:    [ 
    AppComponent 
  ]
})
export class AppModule { }

现在,您需要在要从中发送数据的组件中导入服务(在您的情况下为组件A)

就像是:

import { Component, OnInit } from '@angular/core';
import {NavigationDropdownElements} from './navigation-bar-dropdownElements'

import { MessageService } from './message.service';

@Component({
  selector: 'navigation-bar',
  templateUrl: './navigation-bar.component.html',
  styleUrls: ['./navigation-bar.component.css']
})
export class NavigationBarComponent implements OnInit {
  dropdownElements = NavigationDropdownElements;

  constructor(private messageService: MessageService) {}

  sendMessage(data:string): void {
    // send message to subscribers via observable subject
    this.messageService.sendMessage(data);
  }

  showList() {
    //on a click, you send the message here
    let message:string="data example";
    this.sendMessage(message);
  }

  clearMessage(): void {
    // clear message
    this.messageService.clearMessage();
  }

  ngOnInit() {}

}

最后,您必须在要读取要从第一个组件接收的消息或数据的组件中导入服务(例如,组件B)

就像是:

import { Component, OnInit,  OnDestroy} from '@angular/core';
import { descriptionElements1, descriptionElements2 } from './model-family-description-elements';
import { Subscription } from 'rxjs/Subscription';

import { MessageService } from './message.service';
@Component({
  selector: 'model-family-description',
  templateUrl: './model-family-description.component.html',
  styleUrls: ['./model-family-description.component.css']
})
export class ModelFamilyDescriptionComponent implements OnInit {
  //you receive the data in this variable --> message
  message: any;
  subscription: Subscription;

  desc1 = descriptionElements1;
  desc2 = descriptionElements2;

  constructor(private messageService: MessageService) {

  }

  ngOnDestroy() {
    // unsubscribe to ensure no memory leaks
    this.subscription.unsubscribe();
  }

  ngOnInit() {
    // subscribe to component A messages
    this.subscription = this.messageService.getMessage().subscribe(message => { this.message = message; });
  }

}
另一答案

有两种方法可以使用EventEmitter或使用Subject我更喜欢Subject。你可以从rxjs lib http://reactivex.io/rxjs/file/es6/Subject.js.html#lineNumber19的文档中阅读更多关于Subject的信息,如果你想了解更多关于EventEmitter https://angular.io/api/core/EventEmitter的信息,它不是一个与EventEmitter不同的角度实现函数

另一答案

您需要从组件A发出下拉选项更改

然后使用setter方法从组件B和C接收更改。在值更新期间始终调用Setter方法。

点击这里:https://stackblitz.com/edit/angular-dshm6g

您还可以使用rxJs中的可观察模式来解决此类问题。

以上是关于如何根据Angular中一个组件中的click事件更改其他组件中的数据?的主要内容,如果未能解决你的问题,请参考以下文章

模板中的Angular 2重复组件引用另一个元素

angular2测试,如何测试事件绑定到一个元素

如何在单击事件Angular5上显示组件选择器

Angular中的单元测试点击事件

Angular 材料 2:如何区分一个组件中的 2 个或多个可排序表?

Angular2如何在不点击的情况下触发(点击)事件