简体   繁体   English

在 angular html 模板中显示来自ngrx 存储的单个 object

[英]Displaying a single object from ngrx store in the angular html template

I need help with displaying an object.我需要有关显示 object 的帮助。 The code is as follows:代码如下:

office.action.ts: office.action.ts:

export const getOfficeRequest = createAction('[Office] Get Office Request', props<{key: string}>());
export const getOfficeDone = createAction('[Office] Get Office Request Done', props<{office: Office}>());

office.reducer.ts: office.reducer.ts:

@Effect()
  getOffice$ = this.action$.pipe(
    ofType(getOfficeRequest),
    switchMap((action) => this.OFMService.getOffice(action.key)
    .pipe(
      map((office: Office) =>  getOfficeDone({ office })))
    )
  );

component.module.ts:组件.module.ts:

import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { faEllipsisV, faPhoneAlt, faUserFriends } from '@fortawesome/free-solid-svg-icons';
import { OfficeComponent } from './office-list/office/office.component';
import { NgModule } from '@angular/core';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';

import { CommonModule } from '@angular/common';

import {EffectsModule} from '@ngrx/effects';
import { officesReducer } from './../shared';

import { ComponentsRoutingModule } from './components-routing.module';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import { RouterModule } from '@angular/router';
import { OfficeListComponent } from './office-list/office-list.component';
import {OfficeDetailsComponent} from './office-list/office-details/office-details.component';
import {OfficeEffects} from './../shared/store/effects/office.effects';


import {  ReactiveFormsModule } from '@angular/forms';
import { LoadingComponent, ModalModule } from '../shared';
import { StaffComponent } from './staff/staff.component';
import { StoreModule } from '@ngrx/store';



@NgModule({
  declarations: [OfficeComponent, OfficeListComponent, OfficeDetailsComponent, StaffComponent, LoadingComponent],
  imports: [
    CommonModule,
    ComponentsRoutingModule,
    FontAwesomeModule,
    RouterModule,
    ReactiveFormsModule,
    StoreModule.forRoot({ offices: officesReducer }),
    StoreDevtoolsModule.instrument(),
    EffectsModule.forRoot([ OfficeEffects ]),
    NgbModule,
    ModalModule],
})
export class ComponentsModule {
  constructor() {
    library.add(faPhoneAlt, faEllipsisV, faUserFriends);
  }
}

office-details.component.ts: office-details.component.ts:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Store, select } from '@ngrx/store';
import { getOfficeRequest } from 'src/app/shared';

import { Office } from 'src/app/shared/models/office.model';
import { OfficemanService } from '../../../shared/services/officeman.service';

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

  office$ = this.store.pipe(select(theState => theState.office));
  // office: Office;
  id: string;
  constructor(
    private officeMan: OfficemanService,
    private route: ActivatedRoute,
    private router: Router,
    private store: Store<{office: Office}>) {
    this.id = route.snapshot.params.id;
  }

  ngOnInit(): void {
    const key = this.id;
    this.store.dispatch(getOfficeRequest({key}));
  }

}

office-details.component.html office-details.component.html


<div class="office-details text-center text-white" *ngIf="(office$ | async); let office;">
    <div class="office-details__office-card bg-primary shadow mx-2 mb-3">
        <div class="office-details__header text-white text-left px-4 pt-4 h3" [routerLink]="'/'"><i class="fas fa-arrow-left pr-4"></i>{{office?.officeName }}</div>
        <div class="office-details_contact-details text-left p-4 pt-2">
            <div class="office-details__address">Address: {{office | json}}</div>
            <div class="office-details__email">Email: {{office?.email }}</div>
            <div class="office-details__office-tel">Office Tel: {{office?.officeTel }}</div>
            <div class="office-details__max-capacity">Max Capacity: {{office?.maxOccupants }}</div>
        </div>
    </div>
    <app-staff [office]="office$" ></app-staff>
</div>

<app-loading *ngIf="!office$"></app-loading>

The redux tools show that the object is being retrieved from the store but I can't display it on the html template. redux 工具显示正在从商店检索 object,但我无法在 html 模板上显示它。 I have read many of the other entries on here but they don't work on my case.我已经阅读了这里的许多其他条目,但它们不适用于我的情况。

在此处输入图像描述

It's not showing any error messages on the console.它没有在控制台上显示任何错误消息。 But when I try console.log the this.office it show that there is an observable and the values are present.但是当我尝试 console.log this.office时,它显示有一个 observable 并且值存在。 I don't know how to diplay them though.我不知道如何显示它们。 YOu help will be much appreciated.您的帮助将不胜感激。 I'm using Angular11.我正在使用 Angular11。

There are a couple of things going on here.这里发生了几件事。 Observables have to be subscribed to in order to listen to values produced.必须订阅 Observables 才能监听产生的值。 In the template, use the AsyncPipe to subscribe to the observable and get its values.在模板中,使用 AsyncPipe 订阅 observable 并获取其值。

The other part is variable reassigment.另一部分是变量重新分配。 You've subscribed to the "office$" observable using the async pipe, and reassigned it to "office", so you can just use the "office" value for the rest.您已经使用异步 pipe 订阅了可观察的“office$”,并将其重新分配给“office”,因此您可以只使用 rest 的“office”值。

Anything outside the div with the *ngIf will need to use the async pipe again.带有 *ngIf 的 div 之外的任何内容都需要再次使用异步 pipe。

<div class="office-details text-center text-white" *ngIf="(office$ | async); let office;">
    <div class="office-details__office-card bg-primary shadow mx-2 mb-3">
        <div class="office-details__header text-white text-left px-4 pt-4 h3" [routerLink]="'/'"><i class="fas fa-arrow-left pr-4"></i>{{office?.officeName }}</div>
        <div class="office-details_contact-details text-left p-4 pt-2">
            <div class="office-details__address">Address: {{office | json}}</div>
            <div class="office-details__email">Email: {{office?.email }}</div>
            <div class="office-details__office-tel">Office Tel: {{office?.officeTel }}</div>
            <div class="office-details__max-capacity">Max Capacity: {{office?.maxOccupants }}</div>
        </div>
    </div>
    <app-staff [office]="office" ></app-staff> <! -- here -->
</div>

<app-loading *ngIf="!(office$ | async)"></app-loading> <!-- here -->

In the office.reducer.ts:在 office.reducer.ts 中:

const office = new Office();

export const officeReducer = createReducer<Office>(office,
    on(getOfficeDone, (_, action) => action.office));

I added a selector which I will use to send the intercepted/copied data to the store.我添加了一个选择器,用于将截获/复制的数据发送到商店。

Then I modified the component.module.ts:然后我修改了component.module.ts:

 StoreModule.forRoot({ offices: officesReducer, office: officeReducer }),

This all I had left out in my solution.这是我在解决方案中遗漏的全部内容。 The Object is now populating the template as planned. Object 现在正在按计划填充模板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM