首页 > 解决方案 > Angular 6,根据所选值从 GET http 调用中获取过滤后的数据,无需管道

问题描述

我正在使用分别构建的 Angular 6 和 ASP.NET Core 2.0。我有一个 HTTP GET 调用,它将位置列表返回到下拉列表。我想过滤 TeacherName 选项/下拉列表以仅显示与下拉列表中选择的位置相同的名称(在后端 SQL 数据库中)。浏览器中的错误说... TypeError: Cannot read property 'filter' of undefined

所以,我认为“filterTeachers”函数中的语法不正确,但它可能是别的东西(?)。Angular 可以在没有管道的情况下进行这些类型的客户端过滤吗?它应该作为 linq 查询而不是在后端完成吗?

这里是 update.component.html...

<div>
  <form>  
<div class="form-group">
  <label for="LogLocation-input">Select Your Location </label>
  <select type="text" id="LogLocation" name="LogLocation-input" [(ngModel)]="teacherLocInput" (ngModelChange)="basedOnLoc($event)" class="form-control"> 
<option *ngFor="let loc of teacherLocationsData" [value]="loc.location">
  {{ loc.location }}
</option>
  </select>
</div>

<div class="form-group">
  <label for="TeacherName-input">Enter Teacher Name </label>
  <select type="text" id="TeacherName" name="TeacherName-input" [(ngModel)]="loggingInfo.ClassTimesTeacherName" class="form-control">
    <option *ngFor="let nam of filteredTeacherNames"> 
      {{ nam.name }}
    </option>  
  </select>
</div>


      <button type="button" class="btn btn-primary" (click)="addOrUpdateLoggingRecord($event);">Save</button>

      <h2 *ngIf="!loggingInfo || loggingInfo.id === undefined">Add record</h2>

      <h2 *ngIf="loggingInfo && loggingInfo.id !== undefined">Update record (ID: )</h2>

  </form>
 </div>

这是 update.component.ts...

import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core';
import { TimeService } from '../time.service';


@Component({
  selector: 'app-update',
  templateUrl: './update.component.html',
  styleUrls: ['./update.component.css']
})
export class UpdateComponent implements OnInit {
  @Output() loggingCreated = new EventEmitter<any>();
  @Input() loggingInfo: any;
  public buttonText = 'Save';
  public teacherLocationsData: Array<any>;   
  public teacherNameData: Array<any>;
  public filteredTeacherNames: Array<any>;

  private _teacherLocInput: string;
  get teacherLocInput(): string {
    return this._teacherLocInput;
  }
  set teacherLocInput(value: string) {
  this._teacherLocInput = value;
  this.filteredTeacherNames = this.filterTeachers(value);
}

filterTeachers(teacherLocInput: string) {
  return this.teacherNameData.filter(teacher => teacher.location === this.teacherLocInput);
}


  constructor(private timeService: TimeService) { 
    this.clearAllInfo();
    timeService.getTeacherLocation().subscribe((importLocations: any) => this.teacherLocationsData = importLocations);   
 }

  ngOnInit() {
    // not sure if needed
    this.teacherNameData;

  }

basedOnLoc(val:any) {
  // not sure if this is calling API
this.customFunction(val);
}

// gets called on the change event of location selected
customFunction(val:any) {
  this.teacherLocInput = val; 
  this.timeService.getTeacherName().subscribe((importTeacherName: any) => this.teacherNameData = importTeacherName);  
}



  private clearAllInfo = function() {
    // Create an empty logging object
    this.loggingInfo = {
      id: undefined,
      date: '',
      ClassTimesStudentID: '',
      ClassTimesStudentName:'',
      ClassTimesSubjects: '',
      ClassTimesLogLocation: '',
      ClassTimesTeacherID: '',
      ClassTimesTeacherName: '',
      ClassTimesLogOff: '',
      timeInSeconds: 0,
      distanceInMeters: 0
    };
  };

  public addOrUpdateLoggingRecord = function(event) {
    this.loggingCreated.emit(this.loggingInfo);
    this.clearAllInfo();
    console.log(this.LoggingIfo);
  };


}

这是使用 Angular Reactive Forms 的新版本...

import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core';
import { TimeService } from '../time.service';
import { FormGroup, FormBuilder, FormControl } from '@angular/forms';


@Component({
  selector: 'app-update',
  templateUrl: './update.component.html',
  styleUrls: ['./update.component.css']
})
export class UpdateComponent implements OnInit {
  timeLogForm: FormGroup;

  @Output() loggingCreated = new EventEmitter<any>();
  @Input() loggingInfo: any;
  public buttonText = 'Save';

  public teacherLocationsData: Array<any>;
  public teacherNameData: Array<any>;
  public filteredTeacherNames: Array<any>;

  get filterTeachers() {
    return this.teacherNameData.filter(teacher => teacher.location === this.timeLogForm.controls.location.value);
  }
 constructor(private timeService: TimeService, private fb: FormBuilder) { 
    timeService.getTeacherLocation().subscribe((importLocations: any) => this.teacherLocationsData = importLocations);
    timeService.getTeacherName().subscribe((importTeacherName: any) => this.teacherNameData = importTeacherName);
  }

  ngOnInit() { 
    this.buildForm();
  }

  buildForm() {
    this.timeLogForm = this.fb.group({
      id: null,

      ClassTimesLogLocation: null,
      ClassTimesTeacherName: null,

    });
  }
 public addOrUpdateLoggingRecord = function(event) {
    this.loggingCreated.emit(this.loggingInfo);
  };


}

这是反应式表单模板...

<div>
  <form [formGroup]="timeLogForm">
div class="form-group">
  <label for="LogLocation-input">Select Your Location </label>
  <select type="text" id="LogLocation" name="LogLocation-input" formGroupName="ClassTimesLogLocation" class="form-control"> 
<option *ngFor="let loc of teacherLocationsData" [value]="loc.location">
  {{ loc.location }}
</option>
  </select>
</div>

<div class="form-group">
  <label for="TeacherName-input">Enter Teacher Name </label>
  <select type="text" id="TeacherName" name="TeacherName-input" formGroupName="ClassTimesTeacherName" class="form-control">
    <option *ngFor="let nam of filteredTeacherNames" [value]="nam.name" > 
      {{ nam.name }}
    </option>  
  </select>
</div>      <button type="button" class="btn btn-primary" (click)="addOrUpdateLoggingRecord($event);">Save</button>

      <h2 *ngIf="!loggingInfo || loggingInfo.id === undefined">Add record</h2>

      <h2 *ngIf="loggingInfo && loggingInfo.id !== undefined">Update record (id: )</h2>

  </form>
 </div>

标签: angular

解决方案


首先,您正在进行的许多逻辑都可以使用 Angular 的 ReactiveForms 来简化。https://angular.io/guide/reactive-forms老实说,这是我最喜欢的 Angular 部分之一。它使类成为表单而不是模板的唯一真实来源。无论如何,关于你的问题。您可以使用 getter 作为数组来迭代*ngFor. 它将在更改时运行该方法,以便为您处理它。

在您的 .ts 文件中:

get filterTeachers() {
  return this.teacherNameData.filter(teacher => teacher.location === this.teacherLocInput);
}

html:

<option *ngFor="let nam of filterTeachers"> 
  {{ nam.name }}
</option>  

如果您对 ReactiveForms 感兴趣:

component.ts (当然缺少很多你已经拥有的数据):

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';


@Component({
  selector: 'selector-name',
  styleUrls: ['selector-name.component.scss'],
  template: `something.html `
})
export class SomeComponent implements OnInit {

  teacherLocationForm: FormGroup;

  get filterTeachers() {
    return this.teacherNameData.filter(teacher => teacher.location === this.teacherLocationForm.controls.location.value);
  }

  constructor (private fb: FormBuilder) {}

  ngOnInit() {
    this.buildForm();
  }

  buildForm() {
    this.teacherLocationForm = this.fb.group({
      location: null,
      teacher: null
    });
  }


}

HTML:

<div>
  <form [formGroup]="teacherLocationForm">  
<div class="form-group">
  <label for="LogLocation-input">Select Your Location </label>
  <select type="text" id="LogLocation" name="LogLocation-input" formGroupName="location" class="form-control"> 
<option *ngFor="let loc of teacherLocationsData" [value]="loc.location">
  {{ loc.location }}
</option>
  </select>
</div>

<div class="form-group">
  <label for="TeacherName-input">Enter Teacher Name </label>
  <select type="text" id="TeacherName" name="TeacherName-input" formGroupName="teacher" class="form-control">
    <option *ngFor="let nam of filterTeachers"> 
      {{ nam.name }}
    </option>  
  </select>
</div>


      <button type="button" class="btn btn-primary" (click)="addOrUpdateLoggingRecord($event);">Save</button>

      <h2 *ngIf="!loggingInfo || loggingInfo.id === undefined">Add record</h2>

      <h2 *ngIf="loggingInfo && loggingInfo.id !== undefined">Update record (ID: )</h2>

  </form>

然后您的值将更新到该teacherLocationForm属性中。您可以使用 访问它们this.teacherLocationForm.value。表单组非常强大,可以保存表单的状态、错误,并且很容易提交。


推荐阅读