Reputation: 1
I'm new to Angular and am getting an unexpected result from my *ngFor
directive.
When I click the 'add' button a new <li>
element is created, but it's {{ tomato.name }}
data isn't displayed until I refresh the browser:
Screenshots of when I added a 'Test2' input, and after refreshing browser:
added 'Test2'
after refresh
component.html
<div>
<label>Tomato name:
<input #tomatoName />
</label>
<button (click)="add(tomatoName.value); tomatoName.value='';">
add
</button>
</div>
<ul>
<li *ngFor="let tomato of tomatos">
<p>{{ tomato.name }}</p>
</li>
</ul>
component.ts
import { Component, OnInit } from '@angular/core';
import { TomatoService } from '../services/tomato.service';
@Component({
selector: 'app-tomatos',
templateUrl: './tomatos.component.html',
styleUrls: ['./tomatos.component.css']
})
export class TomatosComponent implements OnInit {
tomatos: Tomato[];
constructor(private tomatoService: TomatoService) { }
ngOnInit() {
this.getTomatos();
}
getTomatos(): void {
this.tomatoService.getTomatos()
.subscribe(tomatos => this.tomatos = tomatos)
}
add(name:string): void {
if (!name) { return; }
this.tomatoService.addTomato({name} as Tomato)
.subscribe(tomato => this.tomatos.push(tomato));
}
}
export interface Tomato {
id: number;
name: string;
originPostCode: string;
tastes: string;
}
service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Tomato } from '../tomatos/tomatos.component';
import { Observable, of } from '../../../node_modules/rxjs';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
@Injectable({
providedIn: 'root'
})
export class TomatoService {
private tomatosUrl = 'https://path/tomy/api'
constructor(private http: HttpClient) { }
getTomatos(): Observable<Tomato[]> {
return this.http.get<Tomato[]>(this.tomatosUrl);
}
addTomato (tomato: Tomato): Observable<Tomato> {
return this.http.post<Tomato>(this.tomatosUrl, tomato);
}
}
Thanks in advance!
Upvotes: 0
Views: 1159
Reputation: 490
Use tomato?.name
it will work as this property does not have the value the time it is trying to bind
Upvotes: 0
Reputation: 8712
Import ChangeDetectorRef
from @angular/core
and manually run change detection after this.tomatos.push(tomato)
like below:
constructor(private tomatoService: TomatoService, private ref: ChangeDetectorRef) { }
ngOnInit() {
this.getTomatos();
}
getTomatos(): void {
this.tomatoService.getTomatos()
.subscribe(tomatos => {
this.tomatos = tomatos;
this.ref.detectChanges();
})
}
add(name:string): void {
if (!name) { return; }
this.tomatoService.addTomato({name} as Tomato)
.subscribe(tomato => this.tomatos.push(tomato));
}
Hope this will helps you!
Upvotes: 1