值更改后未定义角度可观察值

时间:2020-06-05 21:12:41

标签: angular typescript

TypeError:无法读取null的属性“ ip”

provider.ts

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { DeviceInterface } from '../interfaces/Device';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class DeviceService {

  private _devices = new BehaviorSubject<DeviceInterface[]>([]);
  private baseUrl = 'api/monitoring';
  private dataStore: { devices: DeviceInterface[] } = { devices: [] };
  readonly devices = this._devices.asObservable();

  constructor(private http: HttpClient) { }

  loadAll() {
    this.http.get<DeviceInterface[]>(`${this.baseUrl}/devices`).subscribe(
      data => {
        this.dataStore.devices = data;
        this._devices.next((<any>Object).assign({}, this.dataStore).devices);
      },
      error => console.log('Could not load todos.')
    );
  }

  create(device: DeviceInterface) {
    this.http
      .post<DeviceInterface>(`${this.baseUrl}/add`, device)
      .subscribe(
        data => {
          this.dataStore.devices.push(data);
          this._devices.next((<any>Object).assign({}, this.dataStore).devices);
        },
        error => console.log('Could not create todo.')
      );
  }


}

component.ts

import { Component, OnInit } from '@angular/core';
import { DialogService, Dialog } from '../providers/dialog.provider';
import { fadeInOut } from '../app.component.animation';
import { AppComponent } from '../app.component'
import {
  LanguageService,
} from '../providers/language.provider';

import { DeviceService } from '../providers/device.provider';
import { DeviceInterface } from '../interfaces/Device';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Component({

  selector: 'app-monitoring',
  templateUrl: './monitoring.component.html',
  styleUrls: ['./monitoring.component.scss'],
  animations: [fadeInOut],
})

export class AppMonitoring implements OnInit {

  dialog: Dialog;
  ShowDevices: boolean;
  devices: Observable<DeviceInterface[]>;

  constructor(
    public language_service: LanguageService,
    public  device_service: DeviceService,
    private dialog_service: DialogService,
    app: AppComponent
  ) {

    app.done$.pipe().subscribe(result => {
      this.ShowDevices = true;
    });

  }

  ngOnInit() {
    this.devices = this.device_service.devices;
    this.device_service.loadAll();
    this.ShowDevices = false;
    this.dialog_service.DialogState.subscribe(dialog => this.dialog = dialog);
  }

  AddDevice() {
    this.dialog = Dialog.DIALOG_ADD;
    this.dialog_service.ChangeDialog(this.dialog);
  }

  Scan() {
    this.dialog = Dialog.DIALOG_SCAN;
    this.dialog_service.ChangeDialog(this.dialog);
  }

}

html模板

  <div [@fadeInOut] *ngIf="ShowDevices">

    <div class="box-header" style="margin-bottom:15px;">
      <div class="div-right" style="line-height: 35px;">

        <a href="#" onclick="return false;" (click)="AddDevice()" class="pull-right"><i matTooltipPosition="below" class="fa fa-plus"></i> </a>
        <a href="#" onclick="return false;" (click)="Scan()" class="pull-right"><i matTooltipPosition="below" class="fa fa-search"></i> </a>
      </div>
    </div>

    <app-device class="flexItemSensor" *ngFor="let device of devices | async; index as i;" [ip]="device?.ip" [name]="device?.name"> </app-device>
  </div>

当我使用添加您

this.device_service.create(post);

已添加新项,但输入值未收到以下错误,应用程序冻结。

使用以下代码在第三个组件中调用create函数本身

  AddDevice() {

    let post: DeviceInterface = {
      ip: this.AddDeviceForm.value.ip,
      name: this.AddDeviceForm.value.name,
    }
    this.device_service.create(post);

  }

无法读取null的属性“ ip”

我知道该项目已成功存储在数据库中,当我重新启动程序时,我可以看到带有其值的新项目,用其值显示添加项目的正确方法是什么?

最诚挚的问候!

编辑:我尝试在ngOnInit()中添加以下代码,并且在要添加的设备上,设备的新值确实为空

 ngOnInit() {

     this.device_service.devices.subscribe(devices => {
      console.log(devices);
    } ); 
    }

编辑2:问题已解决,原来在后端控制器中应返回以下内容:

        return Ok(device);

2 个答案:

答案 0 :(得分:2)

BehaviorSubject将立即发出其在订阅中保留的当前值。到async触发订阅时,observable的值仍为默认值(空数组[])。因此,没有ip属性。

选项1

使用safe navigation operator ?.来检查值是否已定义,然后再尝试访问其属性

<app-device *ngFor="let device of devices | async; index as i;"  [ip]="device?.ip" [name]="device?.name"> </app-device>

选项2

尝试使用*ngIf指令预先检查数组是否为非空。

<ng-container *ngIf="(devices | async) as devicesData">
  <ng-container *ngIf="devicesData.length > 0">
    <app-device *ngFor="let device of devicesData; index as i;"  [ip]="device.ip" [name]="device.name"> </app-device>
  <ng-container>
<ng-container>

答案 1 :(得分:1)

尝试一下

 <app-device *ngFor="let device of devices | async; index as i;"  [ip]="device?.ip" [name]="device?.name"> </app-device>