如何修复“无法读取null的属性”用户名”

时间:2019-04-26 07:47:13

标签: angular

我想将新用户推送到用户数组,但这给我一个错误 错误为“ 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>&nbsp;
                <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">&times;</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>

3 个答案:

答案 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>&nbsp;
                <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属性将为您提供类似 enter image description here 主体将是您的User对象,但它会附带状态代码,标头等。
因此,如果您订阅该Http调用,则必须访问

.subscribe(data => {
  this.users.push(data.body);
}

另一方面,如果您将选项更改为

const httpOptions = {
  headers: new HttpHeaders({ 'Content-Type': 'application/json'}),
  observe: 'body'
};

并订阅该Http调用,您的data(内部订阅)将是body,因此直接是您的User对象。