angular - 在 Angular 中使用 ngModel 时将操作分派(dispatch)到 ngrx/store

标签 angular ngrx-store

我已经在 Angular 10 应用程序中实现了 ng2-search-filter,它工作得很好,并且需要将搜索条件存储在 ngrx/store 中。在下面的代码中,使用 ngModel 将搜索变量读入模板。根据我的理解,需要调度操作,并且通常是通过方法完成的。在这种情况下如何调度操作。我已经在下面编写了调度逻辑,但不知道在哪里调用它。我只是希望我做得正确。

HTML

<div class="container">
  <div class="row">
    <div class="form-group">
      <input type="text" class="form-control" placeholder="Search Here" [(ngModel)]="term">
    </div>
    <div>
      <button class="btnAddCustomer" (click)="addCustomer()"> Add Customer (Template Driven) </button>
    </div>
  </div>
  <div class="row">
    <div class="col-12">
      <table id="customerdetails-table" class="table table-bordered table-striped table-responsive-md" *ngIf="customerDetails">
          <thead>
            <th>Customer</th>
            <th>Company Name</th>
            <th>Contact Name</th>
            <th>Contact Title</th>
            <th>Address</th>
            <th>City</th>
            <th>Region</th>
            <th>Postal Code</th>
            <th>Country</th>
            <th>Phone</th>
            <th>Fax</th>
            <th>Edit</th>
            <th>Delete</th>
          </thead>
          <tbody>
            <tr *ngFor="let custDetails of customerDetails.slice((currentPage - 1) * itemsPerPage,currentPage * itemsPerPage ) | filter:term ">
              <td>{{custDetails.customerId}}</td>
              <td>{{custDetails.companyName}}</td>
              <td>{{custDetails.contactName}}</td>
              <td>{{custDetails.contactTitle}}</td>
              <td>{{custDetails.address}}</td>
              <td>{{custDetails.city}}</td>
              <td>{{custDetails.region}}</td>
              <td>{{custDetails.postalCode}}</td>
              <td>{{custDetails.country}}</td>
              <td>{{custDetails.phone}}</td>
              <td>{{custDetails.fax}}</td>
              <td>
                <a [routerLink]="'/customers'" class="table-row-action edit-action"  (click)="editCustomer(custDetails)">
                  edit
                </a>
              </td>
              <td>
                <a [routerLink]="'/customers'" class="table-row-action edit-action"  (click)="deleteCustomer(custDetails.customerId)">
                  delete
                </a>
              </td>
            </tr>
          </tbody>
        </table>

     
      <pagination [(ngModel)]="currentPage" (pageChange)="pageChanged($event)" [totalItems]="totalItems" [itemsPerPage]="itemsPerPage" [maxSize]="maxSize"></pagination>

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

组件

export class CustomerComponent implements OnInit, OnDestroy  {
  customerDetails: ICustomer[];
  customer: ICustomer;
  public modal: any;
  totalItems: number;
  maxSize = 5;
  currentPage = 1;
  itemsPerPage = 8;
  term: string;
  isEdit: boolean;
  completed$ = new Subject<any>();

  constructor(private customerService: CustomerService,
              public modalService: NgbModal, private store: Store<any>
              ) {
  }

  ngOnInit(): void {
    this.getCustomerDetails();
  }

  getCustomerDetails(): void {
    this.customerService.getCustomerDetails()
      .subscribe(data => {
        this.customerDetails = data;
        this.totalItems = data.length;
      }
      );
  }

  ngOnDestroy(): void {
    this.completed$.next();                      // <-- close impending subscriptions
    this.completed$.complete();
  }

  pageChanged(currentPageIndex: number): void {
    this.currentPage = currentPageIndex;
 }
}

reducer 和 Action

import { createReducer, createAction, on } from '@ngrx/store';

 export const customerReducer = createReducer(
    {term: '' },
    on(createAction('[Customer] Search Term'), state => {
      console.log('original state: ' + JSON.stringify(state));
      return {
        ...state,
         term: state.term
      };
    })
 );

分派(dispatch)操作

  this.store.dispatch(
      {type: '[Customer] Search Term'}
    );

开发工具的屏幕截图

enter image description here

最佳答案

首先,您需要定义将使用什么事件来触发操作。

假设您选择更改,那么您可以执行类似的操作

html

<input type="text" class="form-control" placeholder="Search Here" [(ngModel)]="term" (change)="searchTermChange()">

ts

searchTermChange() {
  this.store.dispatch(customerChangeSearchTerm({ term: this.term }));
}

其中 customerChangeTerm 是操作。顺便说一句,将 Action 、 reducer 、选择器、效果分离到单独的文件中是一个很好的做法。

最后一件事,可能更常见的用例是处理 input 事件。在这种情况下,您将等待 x 个字符,然后执行搜索。

更新

是的,我现在意识到您的州流程中有很多遗漏或错误的事情。首先,您没有在操作中传递术语,其次,您没有使用新术语更新状态。

好的,让我们回顾一下整个过程:

customers.actions.ts

import { createAction, props } from '@ngrx/store';

export const customerChangeSearchTerm = createAction(
  '[Customer] Change Search Term',
  props<{ term: string }>()
);

customers.reducers.ts

import {
  customersChangeSearchTerm
} from './auth.actions';
import { createReducer, on, Action } from '@ngrx/store';

export const initialState: CustomersState = {
  term: null
};

const reducer = createReducer(
  initialState,
  on(customerChangeSearchTerm, (state, payload) => ({
    ...state,
    term: payload.term
  }))
)

顺便说一句,我将 termChange 更改为 searchTermChange

关于angular - 在 Angular 中使用 ngModel 时将操作分派(dispatch)到 ngrx/store,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63029882/

相关文章:

angular - agm-marker 的 markerClick() 返回 null

angular - ActivatedRoute .parent 在 Angular 4 中是一个空对象

css - Chart.js donut Canvas 填充

sql-server - Node js - 导入 mssql 模块以用于 Angular 2 项目错误 : "Can' t resolve 'dns' "and " Can't resolve 'dgram' "

angular - Redux - 如何在大型应用程序中组织商店

angular - 来自 ngrx/store 的 Reducer 不触发

angular - 在 ngrx(带有 ngrx/effects)中,如何检索新创建的项目的 ID?

angular - 如何使 ngrx/store 功能模块与延迟加载的模块一起使用?

Angular 5 导航在守卫返回 Observable 后被取消

input - Angular 2 : What are @input and @output properties