【问题标题】:Angular 7 - Search bar and results in different viewsAngular 7 - 搜索栏和不同视图的结果
【发布时间】:2019-03-27 09:16:22
【问题描述】:

我创建了两个组件:

  • search-bar.component.ts :显示在所有视图中
  • search.component.ts :应该显示结果(来自 REST API 的响应)

工作是这样的:在应用程序的任何地方,我都想执行全局搜索(产品、用户、事件等......)。我在搜索栏中写了一些东西,点击搜索,然后我被重定向到结果页面。结果是从 REST API 获取的。

PS:我在网上找了好几个小时都没找到..奇怪!我确实读过很多关于@Input@Output 的文章。

我接近实现我想要的,用这种代码:

import { Component, OnInit } from '@angular/core';
import {Router} from '@angular/router';

@Component({
  selector: 'app-search-bar',
  templateUrl: './search-bar.component.html',
  styleUrls: ['./search-bar.component.css']
})
export class SearchBarComponent implements OnInit {
  constructor(
    private router: Router
  ) { }

  ngOnInit() {
  }

  onSubmit(search: string, from: string, to: string) {
    this.router.navigate(['recherche'], {
      queryParams: {
        search: search,
        from: from,
        to: to
      }
    });
  }

}

表单是这样构建的:<form ngNoForm class="form-inline"> 和魔术(click)="onSubmit(search.value, from.value, to.value);"

但我不认为这是做这类事情的最佳方式。 (这是我的第一个问题

此外,当我在结果视图中时,如果我再次在搜索栏上进行搜索,它会完全重新加载应用程序,就像它是基本的 href 一样。 (这是我的第二个问题

我没有找到很多用于我需要的用例或示例,但它似乎很基本。

编辑 1:两个组件的代码

search-bar.component.html 的代码:

<div class="event-background-blue margin-20-top">
  <div class="container">
    <!-- Search -->
    <div class="row">
      <div class="col-12">
        <form ngNoForm class="form-inline">
          <div class="row">
            <div class="col">
              <input #search id="search" name="search" class="form-control form-control-lg" type="text" />
            </div>

            <div class="col">
              <div class="input-group date datepicker" data-provide="datepicker" data-date-format="dd/mm/yyyy" data-date-week-start="1" data-date-language="fr">
                <input placeholder="Du" type="text" class="form-control form-control-lg" #from name="from" autocomplete="off" >
                <div class="input-group-append">
                  <span class="input-group-text" id="basic-addon2"><i class="fa fa-calendar" aria-hidden="true"></i></span>
                </div>
              </div>
            </div>

            <div class="col">
              <div class="input-group date datepicker" data-provide="datepicker" data-date-format="dd/mm/yyyy" data-date-week-start="1" data-date-language="fr">
                <input placeholder="Au" type="text" class="form-control form-control-lg" #to name="to" autocomplete="off" >
                <div class="input-group-append">
                  <span class="input-group-text" id="basic-addon2"><i class="fa fa-calendar" aria-hidden="true"></i></span>
                </div>
              </div>
            </div>

            <div class="col">
              <button (click)="onSubmit(search.value, from.value, to.value);" class="btn btn-black" type="submit"><i class="fa fa-search"></i></button>
            </div>
          </div>
        </form>
      </div>
    </div>
  </div>
</div>

search.component.html的代码:

<app-search-bar></app-search-bar>

<div class="container">
  <!-- Header -->
  <div class="row">
    <div class="col-12">
      <h1 class="title-search text-primary">Search</h1>
    </div>
  </div>

  <!-- Count of Events -->
  <div class="row">
    <div class="col-12 margin-20-bottom">
      <h3>Events</h3>
    </div>

    <app-event class="col-12 col-md-6 col-lg-4 mb-10" *ngFor="let event of events" [event]="event"></app-event>

    <div class="col-12" *ngIf="!events">
      <p>No event, go to <a routerLink="/evenements">events !</a></p>
    </div>
  </div>
</div>

编辑 2:添加 search.component.ts 的代码:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { EventService } from '../../../services/event.service';
import { Event, EventsResp, EventsSearch } from '../../../models/event';
import { LocationService } from '../../../services/location.service';
import { Location, LocationsResp, LocationsSearch } from '../../../models/location';

import * as moment from 'moment';

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {

  constructor(
    private route: ActivatedRoute,
    private eventService: EventService,
    private locationService: LocationService,
  ) { }

  perPage: number = 20;
  page: number = 1;
  error: Error;

  locations: Location[];
  events: Event[];

  ngOnInit() {
    // Retreive the parameters
    const search = this.route.snapshot.queryParamMap.get('search');
    const from = this.route.snapshot.queryParamMap.get('from');
    const to = this.route.snapshot.queryParamMap.get('to');

    this.listEvents(search, from, to);
    this.listLocations(search, from, to);
  }

  // listEvents returns all the events
  listEvents(search, from, to): void {
    // Set the parameters
    let parameters: EventsSearch = {
      from: moment(from).toISOString(),
      to: moment(to).toISOString(),
      search: search,
      page: this.page,
      per_page: this.perPage,
      sort: "",
      _location_id: ""
    };

    // List the events
    this.eventService.listEvents(parameters)
      .subscribe((resp: EventsResp) => {
        this.events = resp['events'];
      });
  }

  // listLocations returns all the locations
  listLocations(search, from, to): void {
    // Set the parameters
    let parameters: LocationsSearch = {
      page: this.page,
      is_city_guide: undefined,
      per_page: this.perPage,
      sort: "",
      search: search
    };

    // List the locations
    this.locationService.listLocations(parameters)
      .subscribe((resp: LocationsResp) => {
        this.locations = resp['locations'];
      });
  }
}

编辑3:例如,Google Drive 中的搜索栏就是一个完美的例子,它无处不在,结果显示在结果页面中。

编辑 4

我仔细看了看:Passing @Input and subscribing to @Output while navigating to a Route in Angular 2 Component

还有这个: Angular 5 Pass data on click event from parent component to child component on button clicked at parent component

【问题讨论】:

  • 能否添加两个组件当前的HTML代码?
  • 请分享html文件
  • 好的,让我编辑问题
  • 我添加了请求的两个代码
  • @Elwyn 你可以尝试将你的代码添加到stackblitz

标签: angular rest search


【解决方案1】:

您有两种方法来执行此操作:

快速和基于事件的

在您的搜索栏组件中创建一个事件发射器,并在 onSubmit 函数中触发它,并传递搜索值。

// Search Bar Component

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

@Component({
  selector: 'app-search-bar',
  templateUrl: ['./search-bar.component.html'],
  styleUrls: ['./search-bar.component.scss']
})
export class SearchBarComponent implements OnInit {

@Output() searchEvent = new EventEmitter();

// constructor

  onSubmit(searchValue: string, ...) {
    // your function

    this.searchEvent.emit(searchValue);
  }

}
<!-- Search Component -->

<app-search-bar (searchEvent)="fetchResults($event)">
</app-search-bar>

基于服务的方式

创建父模块中提供的搜索服务,并将其导入两个组件。 在服务中,创建将执行 Http 请求并更新主题的搜索函数。搜索栏组件将在提交时调用此函数。然后创建一个 observable 并从搜索组件中监听它以获取结果。

// Your service

searchResults = new BehaviorSubject<Array<Result>>();

// constructor


onResults() {
  return this.searchResults.asObservable();
}

search(value: string) {
  this.http.post(url, value).subscribe(results => this.searchResults.next(results);
}




// Search-Bar component

onSubmit(value: string) {
  // code
  this.searchService.search(value);
}


// Search component

ngOnInit() {
  this.searchService.onResults().subscribe(results => this.results = results));
}

【讨论】:

  • 非常感谢这个完整的答案,我想“基于服务”是最干净的?
  • 在您的情况下会更好,更具可扩展性。例如,如果您想稍后在其他地方使用结果,那就是解决方案:)
  • 我已经使用了搜索服务,您可以在我在问题中添加的代码中看到它,请问它是否与您的代码匹配?此外,可以肯定的是,BehaviorSubject 只是一个例子,对吧?我的情况是Event[]
  • 我添加了搜索组件的代码,你可以看到我已经使用了一项服务
  • behaviorSubject 是一个容器,允许您从中创建 Observable 并对数据更新做出反应。您可以在您的情况下设置 BehaviorSubject
【解决方案2】:

这种情况只需要使用@input 和@output 这里只需要使用@output并从父组件传递数据

【讨论】:

  • 但是结果是不同的视图,就像您看到的 Google Drive 搜索框?所以我还需要使用navigate 我猜?
  • 让我添加这个例子:我在 PRODUCTS LIST 视图中,我在搜索框中进行搜索,我被重定向到结果视图,它与 PRODUCTS LIST 的视图不同filter,它是一个单独的视图,因为我搜索产品,还搜索用户、事件等...你看到了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-25
  • 1970-01-01
  • 2014-05-22
  • 1970-01-01
  • 1970-01-01
  • 2018-03-26
相关资源
最近更新 更多