【问题标题】:Angular show search result in different componentsAngular 在不同组件中显示搜索结果
【发布时间】:2020-07-19 20:44:21
【问题描述】:

我在主页(homePageComponent)中有搜索功能,当我点击搜索时,它将重定向到名为搜索列表页面(searchListComponent)的不同页面,并且我在 searchListComponent 本身(根据应用程序设计)中还有一个组件,称为搜索卡组件(searchCardComponent),我在其中显示所有搜索结果。我试图使用 eventemitter 将搜索文本从 homePageComponent 发送到 searchCardComponent 但不知何故数据没有通过。如果有人能帮忙就好了。

下面的示例代码

主页组件

HTML(产品 A)

     <ng-select
              class="col-md-5 solution-list-dropdown"
              [items]="productType$ | async"
              [addTag]="true"
              [(ngModel)]="selectedSolutionId"
              bindLabel="description"
              bindValue="id"
              placeholder="Select"
              [clearable]=true
              [searchable]=true
              [dropdownPosition]="'down'"
              [ngClass]="{ 'dropdown-is-invalid': submitted && f.category.errors }">
           </ng-select>
<button class="red-button"  (click)="searchRedirection(selectedSolutionId)">
          Search
        </button>

打字稿

  @Output() searchValue = new EventEmitter<string>();

   public searchRedirection(selectedSolutionId: string) {
      this.searchValue.emit(selectedSolutionId);
      this.router.navigate(['/category/' + selectedSolutionId]);
    }

搜索列表组件

HTML

<div class="container-fluid product-card-container p-0" id="hor-divider">

    <div class="product-list">
      <app-product-card (searchValue)="onApplyEvent($event)" *ngFor="let product of products | filter:searchText | filter:filterText" [product]="product">
      </app-product-card>
    </div>

</div>

打字稿

  onApplyEvent(event: any): any {
    console.log('event : ' + event);
  }

在这里,我希望控制台日志打印“事件:产品 A”,以便我可以利用它将这个值绑定到 *ngFor。任何帮助将不胜感激。

【问题讨论】:

  • 请为您的项目创建一个 stackblitz 并分享它

标签: javascript angular typescript angular-ui-router angular-directive


【解决方案1】:

您可以使用共享服务之类的东西在两个组件之间传输数据,

在此服务中,我们可以使用主题或事件发射器(但主题更好),在主页组件中,我们可以发出主题

在搜索卡片组件中,我们将订阅该主题以检索数据

这是一个例子

shared.service.ts

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

@Injectable({providedIn: 'root'}) // the service is available application wide, so the same instance of this class will be available in the whole application

export class SharedService {

  searchSubject = new Subject<String>(); // a new subject of type String, replace it with your data type
}

在 home 组件中,一旦选择了解决方案,只需将其发送到共享服务,您就可以在 html 中的列表中添加 (change) 或 (ngModelChange) 以检查更改,一旦发生更改,发出主题

所以 home 组件 html 中的函数可能是这样的

(ngModelChange) = "onSelectSolution()"

在ts文件中

constructor(private sharedService: SharedService) { // inject the shared service

}

onSelectSolution() {
  // just emit the event
  this.sharedService.searchSubject.next(this.selectedSolutionId); // emit the value to the shared service
}

然后在搜索卡组件中

import { OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';

// add the selector 

export class SearchCardComponent implements OnInit, OnDestroy {
  subscription: Subscription // define some subscription property to assign the subscription to, and destroy it once we left this component

  constructor(private sharedService: SharedService){}

  ngOnInit() {
    // here to subscribe to the subject in the sharedService
    this.subscription = this.sharedService.searchSubject.subscribe((mySearch: String) => {
      // now we passed the search from the home component to the search card component
    });
  }

  ngOnDestroy() {
    // just unsubscribe the subscription we used
    this.subscription.unsubscribe();
  }
}

查看此链接以查看 (change)(ngModelChange) difference between (change) and (ngModelChange) 之间的区别

【讨论】:

  • 我认为这不适用于常规主题。在发出主题值时不会渲染需要从主题中获取值的组件,这就是为什么在这种情况下 BehaviorSubject 或 ReplaySubject 是更好的选择
  • 啊,是的,你是对的,我以为点击某个按钮后会单独加载searchCard组件,我误解了这个问题,感谢您的澄清:)
【解决方案2】:

您声明的事件发射器不会以这种方式工作,因为它只能由带有 @Output 装饰器的 homePageComponent 的父组件读取。您可以创建一个单独的事件类并将其导入两个组件(一个发出,一个接收),但在我看来这是一种可怕的做法。更好的做法是将搜索词作为查询参数发送到路由中,或者创建一个共享服务,将BehaviorSubject 对象作为字段,因为它可以存储和重新传输最后发出的值。这是参数示例

this.router.navigate(['/category'], { queryParams: { selectedSolutionId: selectedSolutionId } });

然后要获取 SearchListComponent 中的值,您会这样做

import { ActivatedRoute } from '@angular/router';
.....
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.queryParams
  .subscribe(params => {
    this.selectedSolutionId = params.selectedSolutionId;
    //then you could pass this.selectedSolutionId as @Input to app-product-card component
    console.log(this.selectedSolutionId );
  });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-08
    • 2017-06-09
    • 2014-01-20
    • 1970-01-01
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    相关资源
    最近更新 更多