ngrx不维持状态

时间:2018-10-06 08:03:24

标签: angular ngrx-store-4.0

使用一个自己的小商店实现(有效),我试图将ngrx / store引入有角度的6应用程序中。版本是:

"@ngrx/core": "^1.2.0",
"@ngrx/store": "^6.1.0"

该应用程序是一个有角度的前端,可通过Spring应用程序通过http获取/写入数据到数据库。首次加载BankaccountListComponent时,它将通过BankaccountService从数据库中提取银行帐户列表,并随后从spring应用程序中提取。 BankaccountService将提取的数据写入存储中。通过一个可观察到的BankaccountListComponent连接到商店。

但是,它没有获取数据。在客户端中,仅显示一个空框。商店似乎从未更新可观察到的bankaccounts$

仅通过查看下面的代码,对于您来说,错误可能很明显。如果您希望我创建一个可运行的应用程序,例如在jsfiddle中,请让我知道,我会的。

控制台输出为

bankaccountReducer: default action Array [] bankaccount.reducer.ts:24:6
Angular is running in the development mode. Call enableProdMode() to enable the production mode. core.js:3121
BankaccountListComponent: ngOnInit bankaccount-list.component.ts:20:4
BankaccountListComponent: leaving ngOnInit bankaccount-list.component.ts:23:4
BankaccountService: fetched 2 bankaccounts from server bankaccount.service.ts:30:6
BankaccountService: bankaccounts retrieved: Array [ {…}, {…} ] bankaccount.service.ts:33:6
bankaccountReducer: loading data: Array [ {…}, {…} ] bankaccount.reducer.ts:7:6
BankaccountService: bankaccounts dispatched
BankaccountItemComponent: got bankaccount undefined

bankaccount-list.component.html

<div class="bankaccount-list">
  <h1>Bank Accounts</h1>
  <div>
    <app-bankaccount-item *ngFor="let bankaccount of bankaccounts$ | async"
                          [bankaccount]="bankaccount">
    </app-bankaccount-item>
  </div>
</div>

bankaccount-list.component.ts

import {Component, OnDestroy, OnInit} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {BankaccountService} from '../../services/bankaccount.service';
import {Bankaccount} from '../../model/bankaccount';

@Component({
  selector: 'app-bankaccount-list',
  templateUrl: './bankaccount-list.component.html',
  styleUrls: ['./bankaccount-list.component.scss']
})
export class BankaccountListComponent implements OnInit, OnDestroy {

  bankaccounts$: Observable<Bankaccount[]>;
  bankaccountSelectedId: number;

  constructor(private bankaccountService: BankaccountService) {
  }

  ngOnInit() {
    console.log('BankaccountListComponent: ngOnInit');
    this.bankaccounts$ = this.bankaccountService.bankaccounts$;
    this.bankaccountService.getBankaccounts();
    console.log('BankaccountListComponent: leaving ngOnInit');
  }

  ngOnDestroy() {
    console.log('BankaccountListComponent: destroy');
  }
}

bankaccount-item.component.ts

import {Component, EventEmitter, Input, Output} from '@angular/core';
import {Router} from '@angular/router';
import {Bankaccount} from '../../model/bankaccount';

@Component({
  selector: 'app-bankaccount-item',
  templateUrl: './bankaccount-item.component.html',
  styleUrls: ['./bankaccount-item.component.scss']
})
export class BankaccountItemComponent {

  @Input() selected: boolean;
  @Input() bankaccount: Bankaccount;

  @Output() bankAccountSelected = new EventEmitter();
  @Output() bankAccountDeleted = new EventEmitter();

  constructor() {
    console.log('BankaccountItemComponent: got bankaccount', this.bankaccount);
  }
}

bankaccount-item.component.html

<div class="fade-in bankaccount-item" [ngClass]="{selected : selected}" (click)="select()">
  <mat-card>
    <mat-card-content>
      <div class="row">

        <div class="col1">
      <span>
        <a [routerLink]="['./edit', bankaccount.id]"
           (click)="$event.stopPropagation();">{{bankaccount.name}}</a>
      </span>
          <br>
          <span class="grey">{{bankaccount.iban | iban}}</span>
        </div>

        <div class="col2">
          <button mat-button (click)="delete(); $event.stopPropagation()">
            <mat-icon>delete_forever</mat-icon>
          </button>
        </div>

      </div>
    </mat-card-content>
  </mat-card>
</div>

bankaccount.service.ts

import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';

import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import {Bankaccount} from '../model/bankaccount';

import {AppState} from '../model/app.state';
import {Store} from '@ngrx/store';
import * as BankaccountActions from './../store/actions/bankaccount.actions';

const BANKACCOUNTS_URL = 'http://localhost:8090/account/accounts/';

@Injectable()
export class BankaccountService {

  private headers = new HttpHeaders();

  bankaccounts$: Observable<Bankaccount[]>;

  constructor(private httpClient: HttpClient, private store: Store<AppState>) {
    this.headers = this.headers.set('Content-Type', 'application/json');
    this.headers = this.headers.set('Accept', 'application/json');
    this.bankaccounts$ = store.select('bankaccounts');
  }

  getBankaccounts() {
    this.httpClient.get<Bankaccount[]>(BANKACCOUNTS_URL).map((result: any) => {
      console.log('BankaccountService: fetched ' + result._embedded.accounts.length + ' bankaccounts from server');
      return result._embedded.accounts.sort((a, b) => a.id - b.id);
    }).subscribe((bankaccounts) => {
      console.log('BankaccountService: bankaccounts retrieved: ', bankaccounts);
      this.store.dispatch(new BankaccountActions.LoadBankaccounts(bankaccounts));
      console.log('BankaccountService: bankaccounts dispatched');
    });
  }
}

bankaccount.actions.ts

import {Action} from '@ngrx/store';
import {Bankaccount} from '../../model/bankaccount';

export enum BankaccountActionTypes {
  LOAD_BANKACCOUNT = '[Bankaccount] Load',
  ADD_BANKACCOUNT = '[Bankaccount] Add',
  UPDATE_BANKACCOUNT = '[Bankaccount] Update',
  REMOVE_BANKACCOUNT = '[Bankaccount] Remove'
}

export class LoadBankaccounts implements Action {
  readonly type = BankaccountActionTypes.LOAD_BANKACCOUNT;

  constructor(public payload: Bankaccount) {
  }
}

export class AddBankaccount implements Action {
  readonly type = BankaccountActionTypes.ADD_BANKACCOUNT;

  constructor(public payload: Bankaccount) {
  }
}

export class UpdateBankaccount implements Action {
  readonly type = BankaccountActionTypes.UPDATE_BANKACCOUNT;

  constructor(public payload: Bankaccount) {
  }
}

export class RemoveBankaccount implements Action {
  readonly type = BankaccountActionTypes.REMOVE_BANKACCOUNT;

  constructor(public payload: Bankaccount) {
  }
}

export type Actions = LoadBankaccounts | AddBankaccount | UpdateBankaccount | RemoveBankaccount;

bankaccount.reducer.ts

import {Bankaccount} from '../../model/bankaccount';
import * as BankaccountActions from './../actions/bankaccount.actions';

export function bankaccountReducer(state: Bankaccount[] = [], action: BankaccountActions.Actions) {
  switch (action.type) {
    case BankaccountActions.BankaccountActionTypes.LOAD_BANKACCOUNT:
      console.log('bankaccountReducer: loading data: %o', action.payload);
      return [...state, action.payload];
    case BankaccountActions.BankaccountActionTypes.ADD_BANKACCOUNT:
      console.log('bankaccountReducer: adding data %o', action.payload);
      return [...state, action.payload];
    case BankaccountActions.BankaccountActionTypes.UPDATE_BANKACCOUNT:
      console.log('bankaccountReducer: updating data for %o', action.payload);
      return state.map(bankaccount => {
        if (bankaccount.id !== action.payload.id) {
          return bankaccount;
        }
        return action.payload;
      });
    case BankaccountActions.BankaccountActionTypes.REMOVE_BANKACCOUNT:
      console.log('bankaccountReducer: removing bankaccount %o', action.payload);
      return state.filter(bankaccount => bankaccount.id !== action.payload.id);
    default:
      console.log('bankaccountReducer: default action', state);
      return state;
  }
}

app.state.ts

import {Bankaccount} from './bankaccount';

export interface AppState {
  readonly bankaccounts: Bankaccount[];
}

app.module.ts

// ... other imports
import {StoreModule} from '@ngrx/store';
import {bankaccountReducer} from './store/reducer/bankaccount.reducer';
import {BankaccountService} from './services/bankaccount.service';

@NgModule({
  declarations: [
    // ... declarations which have nothing to do with store ...
  ],
  imports: [
    // other imports
    StoreModule.forRoot({bankaccounts: bankaccountReducer})
  ],
  providers: [
    BankaccountService,
    {provide: APP_BASE_HREF, useValue: '/account'}
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

0 个答案:

没有答案