我想将新用户推送到用户数组,但这给我一个错误 错误为“ ERROR TypeError:无法读取属性'Username'为null”
我认为它无法订阅添加的新数据。但是当我刷新浏览器时,我输入的数据已保存在数据库中,并将显示在表格中。
请帮助我。我刚接触角
这是服务user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of} from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { User } from '../classes/user';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'})
};
@Injectable({
providedIn: 'root'
})
export class UserService {
private uri = 'http://localhost:3000/api/users';
constructor(private http: HttpClient) { }
addUser(username: string, password: string, type: string): Observable<User>{
return this.http.post<User>(this.uri, {username, password, type}, httpOptions);
}
getUsers(): Observable<User[]>{
return this.http.get<User[]>(this.uri);
}
deleteUser(userid: number): Observable<User>{
return this.http.delete<User>(`${this.uri}/${userid}`, httpOptions);
}
}
这是组件users.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../../services/user.service';
import { User } from '../../classes/user';
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.css']
})
export class UsersComponent implements OnInit {
users: User[];
constructor(private userservice: UserService) { }
ngOnInit() {
this.getUsers();
}
addUser(username: string, password: string, type: string): void {
this.userservice.addUser(username,password,type).subscribe(data => {
this.users.push(data);
});
}
getUsers(): void {
this.userservice.getUsers().subscribe(data => {
this.users = data;
});
}
deleteUser(userid: number, index): void {
this.users.splice(index, 1);
this.userservice.deleteUser(userid).subscribe();
}
}
这是视图users.component.html
<app-nav></app-nav>
<br>
<div class="container">
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#addusermodal">Add new</button>
<br>
<br>
<table class="table table-striped table-bordered table-hover table-sm">
<thead>
<tr class="table-default">
<th>Username</th>
<th>Password</th>
<th>Type</th>
<th style="width: 150px; text-align: center;">Actions</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users; let i = index;">
<td>{{ user.Username }}</td>
<td>{{ user.Password }}</td>
<td>{{ user.Type }}</td>
<td style="width: 150px; text-align: center;">
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#editusermodal" (click)="getUser(user.UserID)">Edit</button>
<button type="button" class="btn btn-danger btn-sm" (click)="deleteUser(user.UserID, i)">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- add user modal -->
<div class="modal fade" id="addusermodal">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<form>
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title">Add user</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" id="username" placeholder="Enter username" name="username" #username>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" id="password" placeholder="Enter password" name="password" #password>
</div>
<div class="form-group">
<label for="type">Type</label>
<select class="form-control" id="type" name="type" #type>
<option>User</option>
<option>Admin</option>
</select>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" (click)="addUser(username.value, password.value, type.value)">Save</button>
</div>
</form>
</div>
</div>
</div>
答案 0 :(得分:0)
component users.component.ts
您必须初始化变量用户:
解决方案:
users: User[];
为
users: User[] = [];
为什么?
当您使用:[]时,您仅指示数据类型,而没有对其进行初始化
答案 1 :(得分:0)
我建议在您的服务中公开用户的Observable []并将其设置在您的users.component.ts中。然后,您可以使用异步管道在component.html中对其进行订阅。
简短示例:
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of} from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { User } from '../classes/user';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'})
};
@Injectable({
providedIn: 'root'
})
export class UserService {
private uri = 'http://localhost:3000/api/users';
private users: Users[] = [];
private usersSubject = new BehaviorSubject<User[]>(this.users);
users$: Observable<User[]> = this.usersSubject.asObservable();
}
然后,您从api中获取数据,并使用用户$上的数据调用.next()。
在您的users.component.ts中:
import { Component, OnInit } from '@angular/core';
import { UserService } from '../../services/user.service';
import { User } from '../../classes/user';
@Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.css']
})
export class UsersComponent implements OnInit {
users$: Observable<User[]>;
constructor(private userservice: UserService) {
this.users$ = userservice.users$;
}
然后通过使用异步管道订阅可观察对象:
<div *ngIf="users$ | async as users">
<tr *ngFor="let user of users; let i = index;">
<td>{{ user.Username }}</td>
<td>{{ user.Password }}</td>
<td>{{ user.Type }}</td>
<td style="width: 150px; text-align: center;">
<button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#editusermodal" (click)="getUser(user.UserID)">Edit</button>
<button type="button" class="btn btn-danger btn-sm" (click)="deleteUser(user.UserID, i)">Delete</button>
</td>
</tr>
</div>
希望它可以将您推向正确的方向。
答案 2 :(得分:0)
首先,请通过Postman或其他平台检查您的端点是否正常运行并返回正确的User对象。
为您服务
return this.http.post<User>(this.uri, {username, password, type}, httpOptions);
您的httpOptions
在哪里
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'})
};
如果输入http.post
的代码,您会注意到options参数可以接受名为observe
的属性,并且会遇到body
的情况以及是response
。
observe: response
属性将为您提供类似
主体将是您的User对象,但它会附带状态代码,标头等。
因此,如果您订阅该Http调用,则必须访问
.subscribe(data => {
this.users.push(data.body);
}
另一方面,如果您将选项更改为
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'}),
observe: 'body'
};
并订阅该Http调用,您的data
(内部订阅)将是body
,因此直接是您的User对象。