【问题标题】:Subscription to Subject in a pipe doesn't work; Angular4在管道中订阅主题不起作用;角4
【发布时间】:2018-02-16 18:31:17
【问题描述】:

我正在努力订阅 Angular 4 中的选择下拉更改。 我的searchType 变量的更改仅在通过单击事件调用test() 函数后可见,但我需要Angular 立即订阅更改。

旁注:

  • 我正在订阅过滤器管道。
  • 服务在模块中提供,因此在同一个实例上工作

App.component.html

      <select  name="searchType" id="searchType" #searchType>
        <option value="movie_title"> movie title</option>
        <option value="director">director</option>
        <option value="actor"> actor</option>
      </select>

App.component.ts

  @ViewChild('searchType') select: ElementRef;
  searchType: number;

constructor(private service: ServiceService) {}

  ngOnInit() {
    this.searchType = this.select.nativeElement.options.selectedIndex;
    this.service.sendSearchType(this.searchType);
  }

  test() {
  this.searchType = this.select.nativeElement.options.selectedIndex;
  this.service.sendSearchType(this.searchType);
  }

service.service.ts

    searchType = new Subject<number>();

 sendSearchType(id: number) {
     this.searchType.next(id);
 }

 getSearchType(): Observable<number> {
     return this.searchType.asObservable();
 }

最后 filter.pipe.ts 订阅更改

searchType: number;
private subscription: Subscription;

constructor(private service: ServiceService) {
    this.service.getSearchType().subscribe(
        (id) => (this.searchType = id)
    );
}

    transform(value: any[], filter: string): any[] {
        filter = filter ? filter.toLocaleLowerCase() : null;
        return filter ? value.filter(
                (product) =>
                    this.auxiliaryFunction(product, filter)
            ) : value;
    }

    auxiliaryFunction(product, filter) {
        if (this.searchType === 2) {
        return (product.actor.toLocaleLowerCase().indexOf(filter) !== -1)
        } else if (this.searchType === 1) {
        return (product.director.toLocaleLowerCase().indexOf(filter) !== -1)
        }  else {
        return (product.movie.toLocaleLowerCase().indexOf(filter) !== -1)
      }
    }

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }

我哪里做错了? 将不胜感激任何解决方案。

【问题讨论】:

  • 管道用于纯函数,在这种情况下你不应该使用管道,而是将过滤逻辑放在服务中,在你的服务中创建 searchType 主题并订阅它&lt;select name="searchType" (change)="service.searchType.next($event.target.value)"&gt;
  • 你说得对,我实现了你关于将逻辑放入服务的评论,但我不太明白第二部分 - 代码(抱歉,我是初学者;)。我应该改变什么以遵循最佳实践惯例。我把我已经工作的代码放在 [link]stackblitz.com/edit/… 下,你能看看并推荐其他东西是否可以优化吗?
  • 更新:不幸的是,如果我尝试将逻辑外包到服务中,则“搜索依据”过滤器 stos 可以正常工作。问题是我必须再次通过主题传递值 searchType 值 - 甚至可以使用相同的主题还是我必须为此创建另一个主题?

标签: angular observable subscription subject-observer


【解决方案1】:

您必须注意选择元素的变化。我做了这个live example,希望对您有所帮助。 (app.component.ts)

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import { AfterViewInit } from '@angular/core';

...

ngAfterViewInit() {
    const $selector = Observable.fromEvent(this.select.nativeElement, 'change');
    $selector.subscribe(() => {
        this.searchType = this.select.nativeElement.options.selectedIndex;
        this.service.sendSearchType(this.searchType);
    });
}

(filter.pipe.ts)

constructor(private service: AppService) {
    this.service.getSearchType().subscribe(
        (id) => { 
            console.log(`${id}px`);
            return (this.searchType = id);
        }
    );
}

【讨论】:

  • 非常感谢 Luuillyfe,这正在按预期工作:)) 所以基本上,我是否总是必须从通过 observable 发出数据的组件中的服务订阅主题?它是通过 rxjs 将数据流即时获取到另一个组件的唯一方法吗?
  • 不是不是,你可以使用事件绑定,查看我的新答案!
【解决方案2】:

您也可以使用事件绑定 (live exmaple),但我真的更喜欢反应式方法。 (app.component.html)

<select  name="searchType" id="searchType" (change)="onSelect()" #searchType>
    <option value="movie_title">movie title</option>
    <option value="director">director</option>
    <option value="actor"> actor</option>
</select>

(app.component.ts)

onSelect() {
      this.searchType = this.select.nativeElement.options.selectedIndex;
      this.service.sendSearchType(this.searchType);
  }

【讨论】:

    猜你喜欢
    • 2020-12-13
    • 1970-01-01
    • 2023-03-22
    • 2020-01-20
    • 2017-01-19
    • 2018-08-14
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    相关资源
    最近更新 更多