首页 > 解决方案 > 由于类型冲突,将用户输入推送到 Typescript 数组的问题

问题描述

我有一个名为friend的类,包含一个数组作为属性:

export class Friend {
  id: number;
  name: string;
  bday: string;
  gifts: string[] = [];
}

我正在尝试根据用户对朋友详细信息组件的输入来访问它并将项目推入其中:

export class FriendDetailComponent implements OnInit {
  @Input() friend: Friend;


  constructor(
    private route: ActivatedRoute,
    private friendService: FriendService,
    private location: Location,
  ) { }

  ngOnInit(): void {
    this.getFriend();

  }

  getFriend(): void {
    const id = +this.route.snapshot.paramMap.get('id');
    this.friendService.getFriend(id)
        .subscribe(friend => this.friend = friend);
  }

  goBack(): void {
    this.location.back();
  }

  addGift(): void {
    var giftinput = (<HTMLInputElement> document.getElementById("gift-input")).value;
    var gifts = this.friend.gifts;
    console.log(typeof(this.friend.gifts));
    console.log(this.friend.gifts);
    gifts.push(giftinput);
  }
}

用户输入的 html 如下所示:

<div *ngIf="friend">
  <h2>{{ friend.name | uppercase }} Details </h2>
  <div><span>id: </span> {{friend.id}}</div>
  <div>
    <label>Name:
      <input [(ngModel)]="friend.name" placeholder="name">
    </label>
    <br>
    <label>Birthday:
      <input [(ngModel)]="friend.bday" placeholder="bday">
    </label>
    <br>
    <label>Gift Ideas:
      <input id="gift-input" [(ngModel)]="friend.gifts" placeholder="gift">
      <p [(ngModel)]="friend.gifts" ngDefaultControl>{{friend.gifts}}</p>
      <button (click)="addGift()">add gift</button>
    </label>
    <!-- <button (click)="addGift()">Add Gift</button> -->
  </div>
</div>

<button (click)="goBack()">go back</button>

我不相信这段代码是问题的一部分,但以防万一:

export class FriendService {
  //url to web api and friends object
  private friendsUrl = 'api/friends';


  getFriends(): Observable<Friend[]> {
    //this.messageService.add('FriendService: fetched friends');
    return this.http.get<Friend[]>(this.friendsUrl)
    .pipe(
      //_ refers to unused parameter
      tap(_ => this.log(`fetched friends`)),
      catchError(this.handleError('getFriends', []))
    );
  }

  private handleError<T> (operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
      console.error(error);
      this.log(`${operation} failed: ${error.messages}`);
      return of(result as T);
    }
  }

  getFriend(id: number): Observable<Friend> {
    //todo: send message after fetching the Hero
    //this.messageService.add(`FriendService: fetched friend id=${id}`);
    const url = `${this.friendsUrl}/${id}`;
    return this.http.get<Friend>(url).pipe(
      tap(_ => this.log(`fetched friend id=${id}`)),
      catchError(this.handleError<Friend>(`getFriend id=${id}`))
    );
  }

  updateFriend(friend: Friend): Observable<any> {
    return this.http.put(this.friendsUrl, friend, httpOptions).pipe(
      tap(_ => this.log(`updated friend id=${friend.id}`)),
      catchError(this.handleError<any>(`updateFriend`))
    );
  }

  addFriend(friend: Friend): Observable<Friend> {
    return this.http.post<Friend>(this.friendsUrl, friend, httpOptions).pipe(
      tap((newFriend: Friend) => this.log(`added friend w/ id=${newFriend.id}`)),
      catchError(this.handleError<Friend>(`addFriend`))
    );
  }

  searchFriends(term: string): Observable<Friend[]> {
    if (!term.trim()) {
      return of([]);
    }
    return this.http.get<Friend[]>(`${this.friendsUrl}/?name=${term}`).pipe(
      tap(_ => this.log(`found friends matching "${term}"`)),
      catchError(this.handleError<Friend[]>('searchFriends', []))
    );
  }

  deleteFriend(friend: Friend | number): Observable<Friend> {
    const id = typeof friend === 'number' ? friend : friend.id;
    const url = `${this.friendsUrl}/${id}`;

    return this.http.delete<Friend>(url, httpOptions).pipe(
      tap(_ => this.log(`deleted friend id=${id}`)),
      catchError(this.handleError<Friend>('deleteFriend'))
    );
  }

  private log(message: string) {
    this.messageService.add(`FriendService: ${message}`);
  }

  constructor(
    private http: HttpClient,
    private messageService: MessageService,) { }
}

当用户输入为空时调用 addGift() 函数(按下按钮),打印语句返回“object”和一个空数组“[]”。但是,只要我在用户输入中输入一个值,打印语句就会显示“字符串”,并且 push 函数会启动错误:

ERROR TypeError: gifts.push is not a function

我错过了什么?类型是否在改变,为什么?

标签: angulartypescript

解决方案


类型确实在变化。您在课堂上声明 .gifts 是一个数组,但在您的 html 中,您使用 ngModel 将其绑定到文本输入。When 意味着当您的用户在框中键入时,您正在积极地将该值重新分配为字符串。

这是您可能要重新考虑/删除 ngModel 的行

<input id="gift-input" [(ngModel)]="friend.gifts" placeholder="gift">

推荐阅读