将管道逻辑转换为ngrx reducer是否可以?

时间:2017-02-06 13:12:03

标签: angular ngrx

我是ngrx-store的新手,我只是想知道在存储器reducer中编写逻辑(例如搜索逻辑)而不是管道本身是否可以,或者只是将它们分开,因为管道导致应用程序状态改变

以下是小示例代码段。假设,我想基于用户输入字符串搜索 / 过滤器待办事项列表。

todo.pipe.ts

<?php

   $item_data = PodioItem::get_basic( $podio_item_id );

   $car_types = $item_data->fields["car-type"]->config['settings']['options'];

   var_dump( $car_types );

?>

app.component.ts

import { Pipe, PipeTransform } from '@angular/core';
import { Todo } from '../todo.model/todo.model';

@Pipe({
    name: 'searchPipe'
})
export class TodoSearchPipe implements PipeTransform{
    transform(values: Todo[], term: string){
        return values.filter(obj => obj.name.startsWith(term))
    }
}

TodoSearchPipe 一样,行import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; import { Todo } from '../todo.model/todo.model'; import { TodoService } from '../todo.service/todo.service'; import { TodoSearchPipe } from '../todo.pipe/todo.pipe'; @Component({ selector:'main-app', template: ` <h3>Todo List</h3> <ul> <li *ngFor = 'let todo of $todoList | async | searchPipe: userSearchInput'> {{ todo.name }} - {{ todo.desc }} <li> </ul><br/> Search By Name: <input type='text' [(ngModel)] = 'userSearchInput'/> ` }) export class AppComponent implements OnInit{ private $todoList:Observable<Todo[]>; private userSearchInput: string = ""; constructor(private _store: Store<Number>, private _service: TodoService){} ngOnInit(){ this.$todoList = this._store.select('todos'); } } 会导致应用程序状态更改。如果我们从这里为减速器派遣事件并在那里写这个过滤器线怎么办?这样做是否可行,如果是,如何实现这一目标?

ngrx商店代码段在这里:

values.filter(obj => obj.name.startsWith(term))

2 个答案:

答案 0 :(得分:1)

我会通过在状态中单独保存搜索词和待办事项来在商店而不是管道中处理此问题。这样您就可以在商店中看到您的待办事项列表和您当前的搜索字词(从而使调试更容易)。然后,您可以从商店中进行选择,合并这两个数据,并在列表中使用它们。

像这样。

app.component.ts:

    @Component({
        selector:'main-app',
        template:
            <h3>Todo List</h3>
            <ul>
                <li *ngFor = 'let todo of $filteredList | async'>
                    {{ todo.name }} - {{ todo.desc }}
                <li>
            </ul><br/>
            Search By Name: <input type='text' (keyup)="onkeyup($event.target.value)"/>
    })
    export class AppComponent implements OnInit{
        private $filteredList: Observable<Todo[]>;
        private userSearchInput: string = "";

        constructor(private _store: Store<Number>, private _service: TodoService){}

        ngOnInit(){
            this.$filteredList = this._store.select('todos').map(theState => {
                theState.todos.filter(todo => todo.contains(theState.searchTerm));
            });
        }

        onkeyup(val) {
            // dispatch the input's value to the store
            this.store.dispatch({type: 'INPUT_SEARCH', action: val);
        }
}

减速机:

import { Action, ActionReducer } from '@ngrx/store';
import { Todo } from '../todo.model/todo.model';

const initialState: any = {
    todos: [],
    searchTerm: ''
}

export const todoStore: ActionReducer<Todo> = (state = initialState, action: Action) => {
    switch (action.type) {
        case "SET_LIST":
            return Object.assign({}, state, {
                todos: action.payload
            });
        case "INPUT_SEARCH":
            return Object.assign({}, state, {
                searchTerm: action.payload
            });
        default: return state;
    }
}

答案 1 :(得分:1)

杰森的回答将起作用,你可以做到。

但如果需要,如何在其他地方显示filteredList

想象一下这个“过滤器”非常庞大,比如... 50~100行甚至更多。你会每次复制吗?

您应该使用“选择器”:http://redux.js.org/docs/recipes/ComputingDerivedData.html

我们的想法是保持您的商店不受影响,使用原始数据,只需在您所处的状态中设置您要过滤的属性。 (例如称之为“搜索”)。

然后,您可以像这样构建选择器:

function getMyComputedData() {
  return function(store: Store<IStore>) {
    store.select(state => state...) // whatever you want to filter
  }
}

在您的组件中,只需使用它:

@Component({
  // ...
})
export class YourComponent {
  private computedData$: Observable<any>;

  constructor(private store: Store<IStore>) {
    this.computedData$ = this.store.let(getMyComputedData());
  }
}

每次商店更改时,选择器都会更新(根据您在选择器中select的内容而变化),您可以在任何需要的地方使用它。

<小时/> 您可能需要查看:
- 我在Plunkr上使用Redux进行的工作演示,仅用于normalized data和选择器 - 我使用Angular(V2.x),angular / cli和ngrx构建的完整演示项目:Pizza Sync
(选择器位于here并在此view中使用)