属性 在 Angular 9 上的 Observable 类型上不存在
Property does not exist on type Observable on Angular 9
仅当我使用双向绑定访问其属性时,模板上的类型 Observable 对象似乎未定义。当我尝试使用 {{interpolation}} 语法访问 属性 时,它起作用了。例如:<h1>{{flight.airline}}</h1>
有效但 <input type="text" class="form-control" id="airline" name="airline" [(ngModel)]="flight.airline">
无效。任何使用双向绑定的元素都有这个问题。
我尝试使用 elvis 运算符 ?.
并使用 *ngIf
指令,认为这是因为数据最初不可用,但出现了同样的错误。如果有人能指出我做错了什么,我将不胜感激
航班-edit.component.html
<div class="container">
<h1>Flight Scheduler</h1>
<div class="col-lg-8 ">
<h3 *ngIf="success" class="text-success">Successfully updated!</h3>
<h4 class="float-right"><small>All fields are required</small></h4>
<div class="row well center">
<form (ngSubmit)="onSubmit()">
<div class="col-sm-12">
<div *ngIf="flight" class="row">
<div class="col-sm-6 form-group">
<label>Airline</label>
<input type="text" class="form-control" id="airline" name="airline" [(ngModel)]="flight.airline">
</div>
<div class="col-sm-6 form-group">
<label>Flight Number</label>
<input type="text" class="form-control" name="flight_no" [(ngModel)]="flight.flight_no">
</div>
</div>
<div class="form-group" style="border:1px solid #ced4da; padding:10px; border-radius: 5px;">
<label>Trip Type</label>
<div *ngIf="flight" class="radio">
<ng-container *ngFor="let trip_type of trip_types; let i=index">
<label for="radios-{{i}}" style="margin-right:20px">
<input type="radio" name="trip_type" id="radios-{{i}}"
[checked]="flight.trip_type==trip_type"
[value]="trip_type"
(change)="flight.trip_type=trip_type">
{{trip_type}}
</label>
</ng-container>
</div>
</div>
<div *ngIf="flight" class="row">
<div class="col-sm-6 form-group">
<label>Departure Airport</label>
<input type="text" class="form-control" name="departure_airport" [(ngModel)]="flight.departure_airport">
</div>
<div class="col-sm-6 form-group">
<label>Arrival Airport</label>
<input type="text" class="form-control" name="arrival_airport" [(ngModel)]="flight.arrival_airport">
</div>
</div>
<div *ngIf="flight" class="row">
<div class="col-sm-6 form-group">
<label>Departure Date</label>
<input type="date" class="form-control" name="departure_date" [(ngModel)]="flight.departure_date">
</div>
<div class="col-sm-6 form-group">
<label>Return Date</label>
<input type="date" class="form-control" name="return_date" [(ngModel)]="flight.return_date">
</div>
</div>
<button type="submit" class="btn btn-lg btn-info">Submit</button>
</div>
</form>
</div>
</div>
</div>
航班-edit.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable, ObservedValueOf } from "rxjs";
import { Flight } from "../models/flight";
import { FlightService } from "../services/flight.service";
import { ActivatedRoute } from "@angular/router";
@Component({
selector: 'app-flight-edit',
templateUrl: './flight-edit.component.html',
styleUrls: ['./flight-edit.component.css']
})
export class FlightEditComponent implements OnInit {
flight: Observable<Flight>;
flight_id: number;
success: boolean = false;
trip_types = ["One Way","Round Trip","Multiple Destinations"];
constructor(private flightService: FlightService,
private activatedRoute: ActivatedRoute) { }
ngOnInit() {
this.activatedRoute.paramMap.subscribe(
params => {
this.flight_id = Number(params.get("id"));
}
);
this.loadFlightData();
}
loadFlightData(){
this.flightService.getFlight(this.flight_id)
.subscribe(
data => {
this.flight = data;
}
);
}
updateFlight(){
this.flightService.updateFlight(this.flight_id,this.flight)
.subscribe(
data => {
this.flight = data as Observable<Flight>;
this.success = true;
},
error => console.log("Oops. Cannot update! " + error)
);
}
onSubmit(){
this.updateFlight();
}
}
flight.service.ts
import { Injectable } from '@angular/core';
import {HttpClient } from '@angular/common/http'
import { Observable } from 'rxjs'
import { Flight } from '../models/flight'
@Injectable({
providedIn: 'root'
})
export class FlightService {
private endpoint = 'http://127.0.0.1:8000/flights/';
constructor(private http: HttpClient) {}
getFlight(id: number): Observable<any>{
return this.http.get(this.endpoint + id)
}
//GET all flights
getAllFlights(): Observable<any>{
// console.log(this.http.get(this.endpoint))
return this.http.get(this.endpoint)
}
//POST - add new flight
flightCreate(flight: Flight): Observable<object>{
return this.http.post(this.endpoint, flight)
}
//PUT - update
updateFlight(id: number, payload: any): Observable<object> {
return this.http.put(this.endpoint + id, payload)
}
}
嗯,我们需要做一些改变。
在FlightEditComponent
// Comment the line below, let's change the attribute name and type
// flight: Observable<Flight>;
_flight$ = new BehaviorSubject<Flight | null>(null);
...
ngOnDestroy() {
// best practice: complete all your subjects on component removal
if(this._flight$ && !this._flight$.closed) {
this._fligth$.complete();
}
}
...
loadFlightData(){
this.flightService.getFlight(this.flight_id)
.subscribe(data => this._flight$.next(data));
}
在模板中
替换为:
<div *ngIf="flight" class="row">
有了这个:
<div *ngIf="_flight$ | async as flight" class="row">
仅当我使用双向绑定访问其属性时,模板上的类型 Observable 对象似乎未定义。当我尝试使用 {{interpolation}} 语法访问 属性 时,它起作用了。例如:<h1>{{flight.airline}}</h1>
有效但 <input type="text" class="form-control" id="airline" name="airline" [(ngModel)]="flight.airline">
无效。任何使用双向绑定的元素都有这个问题。
我尝试使用 elvis 运算符 ?.
并使用 *ngIf
指令,认为这是因为数据最初不可用,但出现了同样的错误。如果有人能指出我做错了什么,我将不胜感激
航班-edit.component.html
<div class="container">
<h1>Flight Scheduler</h1>
<div class="col-lg-8 ">
<h3 *ngIf="success" class="text-success">Successfully updated!</h3>
<h4 class="float-right"><small>All fields are required</small></h4>
<div class="row well center">
<form (ngSubmit)="onSubmit()">
<div class="col-sm-12">
<div *ngIf="flight" class="row">
<div class="col-sm-6 form-group">
<label>Airline</label>
<input type="text" class="form-control" id="airline" name="airline" [(ngModel)]="flight.airline">
</div>
<div class="col-sm-6 form-group">
<label>Flight Number</label>
<input type="text" class="form-control" name="flight_no" [(ngModel)]="flight.flight_no">
</div>
</div>
<div class="form-group" style="border:1px solid #ced4da; padding:10px; border-radius: 5px;">
<label>Trip Type</label>
<div *ngIf="flight" class="radio">
<ng-container *ngFor="let trip_type of trip_types; let i=index">
<label for="radios-{{i}}" style="margin-right:20px">
<input type="radio" name="trip_type" id="radios-{{i}}"
[checked]="flight.trip_type==trip_type"
[value]="trip_type"
(change)="flight.trip_type=trip_type">
{{trip_type}}
</label>
</ng-container>
</div>
</div>
<div *ngIf="flight" class="row">
<div class="col-sm-6 form-group">
<label>Departure Airport</label>
<input type="text" class="form-control" name="departure_airport" [(ngModel)]="flight.departure_airport">
</div>
<div class="col-sm-6 form-group">
<label>Arrival Airport</label>
<input type="text" class="form-control" name="arrival_airport" [(ngModel)]="flight.arrival_airport">
</div>
</div>
<div *ngIf="flight" class="row">
<div class="col-sm-6 form-group">
<label>Departure Date</label>
<input type="date" class="form-control" name="departure_date" [(ngModel)]="flight.departure_date">
</div>
<div class="col-sm-6 form-group">
<label>Return Date</label>
<input type="date" class="form-control" name="return_date" [(ngModel)]="flight.return_date">
</div>
</div>
<button type="submit" class="btn btn-lg btn-info">Submit</button>
</div>
</form>
</div>
</div>
</div>
航班-edit.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable, ObservedValueOf } from "rxjs";
import { Flight } from "../models/flight";
import { FlightService } from "../services/flight.service";
import { ActivatedRoute } from "@angular/router";
@Component({
selector: 'app-flight-edit',
templateUrl: './flight-edit.component.html',
styleUrls: ['./flight-edit.component.css']
})
export class FlightEditComponent implements OnInit {
flight: Observable<Flight>;
flight_id: number;
success: boolean = false;
trip_types = ["One Way","Round Trip","Multiple Destinations"];
constructor(private flightService: FlightService,
private activatedRoute: ActivatedRoute) { }
ngOnInit() {
this.activatedRoute.paramMap.subscribe(
params => {
this.flight_id = Number(params.get("id"));
}
);
this.loadFlightData();
}
loadFlightData(){
this.flightService.getFlight(this.flight_id)
.subscribe(
data => {
this.flight = data;
}
);
}
updateFlight(){
this.flightService.updateFlight(this.flight_id,this.flight)
.subscribe(
data => {
this.flight = data as Observable<Flight>;
this.success = true;
},
error => console.log("Oops. Cannot update! " + error)
);
}
onSubmit(){
this.updateFlight();
}
}
flight.service.ts
import { Injectable } from '@angular/core';
import {HttpClient } from '@angular/common/http'
import { Observable } from 'rxjs'
import { Flight } from '../models/flight'
@Injectable({
providedIn: 'root'
})
export class FlightService {
private endpoint = 'http://127.0.0.1:8000/flights/';
constructor(private http: HttpClient) {}
getFlight(id: number): Observable<any>{
return this.http.get(this.endpoint + id)
}
//GET all flights
getAllFlights(): Observable<any>{
// console.log(this.http.get(this.endpoint))
return this.http.get(this.endpoint)
}
//POST - add new flight
flightCreate(flight: Flight): Observable<object>{
return this.http.post(this.endpoint, flight)
}
//PUT - update
updateFlight(id: number, payload: any): Observable<object> {
return this.http.put(this.endpoint + id, payload)
}
}
嗯,我们需要做一些改变。
在FlightEditComponent
// Comment the line below, let's change the attribute name and type
// flight: Observable<Flight>;
_flight$ = new BehaviorSubject<Flight | null>(null);
...
ngOnDestroy() {
// best practice: complete all your subjects on component removal
if(this._flight$ && !this._flight$.closed) {
this._fligth$.complete();
}
}
...
loadFlightData(){
this.flightService.getFlight(this.flight_id)
.subscribe(data => this._flight$.next(data));
}
在模板中
替换为:
<div *ngIf="flight" class="row">
有了这个:
<div *ngIf="_flight$ | async as flight" class="row">