Angular 2:Http获得呼叫,主题未按预期工作

时间:2019-02-23 16:15:59

标签: angular

在我的有角度的应用程序中,我有一个表单Form Page,可以在其中输入员工数据,而我有一个网格页面Grid Page,其中将显示输入的数据。 当我提交表单时,详细信息应添加到网格页面中。

最初,我将从json文件中的网格中获取员工的数据。

我在这里面临的问题是,即使提交表单后,新数据也不会添加到网格中。网格始终从json文件加载。将从表单中推送的数据添加到没有发生的网格中。

在我的服务中,我有以下代码:

import { Employee } from '../employee.model';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs/Subject';
//import 'rxjs/add/operator/map';

@Injectable()
export class BasicServices {

  public newaddFormDetails = new Subject<Employee[]>();
  private _url: string = "/assets/data/employeesData.json";
  public employees: Employee[];

  // private employees: Employee [] =[ {"title":"John", "body":"TL"},
  // {"title":"Kennedy", "body":"SSE"}];
  // getEmployees() {
  //   return this.employees;
  // }

  getEmployees() {
    return this.httpClient.get<Employee[]>(this._url)
    .subscribe(
      (employees:Employee[]) => {
        this.employees = employees;
        this.newaddFormDetails.next(this.employees);
      });
  }

addToGrid(emp: Employee) {
this.employees.push(emp);
this.newaddFormDetails.next(this.employees);
}   

  constructor(private httpClient: HttpClient) {
  }

}

网格组件文件如下:

import { Component, OnInit, OnDestroy} from '@angular/core';
import { BasicServices } from '../services/basic.services';
import { Subscription } from 'rxjs/Subscription';
import { Employee } from '../employee.model';

@Component({
  selector: 'app-grid',
  templateUrl: './grid.component.html',
  styleUrls: ['./grid.component.less']
})

export class GridComponent implements OnInit, OnDestroy{

  subscription: Subscription;
  employees: Employee[];

  constructor( private _basicService: BasicServices) {
  }
  ngOnInit() {
    this.subscription = this._basicService.newaddFormDetails.subscribe(  
      (employees: Employee[]) => {
        this.employees = employees;
       } 
    );
    this._basicService.getEmployees();

  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

}

在我的网格组件html文件中,我只是有一个包含以下代码的表:


<table class='table table-striped table-condensed' *ngIf='employees && employees.length'>
<thead>
    <tr>        
        <th style="min-width: 40px;">Title</th>
        <th style="min-width: 40px;">Body</th>
    </tr>
</thead>
<tbody>
    <tr *ngFor="let emp of employees">
    <td>{{emp.title| uppercase}}</td>
    <td>{{emp.body}}</td>
    <td>
    </tr>
</tbody>
</table>

表单组件文件:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { BasicServices } from '../services/basic.services';
import { Router } from '@angular/router';

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.less']
})
export class FormComponent implements OnInit {
  private form;
    constructor(private _basicService: BasicServices,
      private formBuilder: FormBuilder,
      private router: Router
      ) { }


  ngOnInit() {
   this._basicService.getEmployees();
   this.form = this.formBuilder.group({
      title: [null, Validators.required],
      body: [null, Validators.required],
    });

  }

  onSubmit(formValue):void {
    this._basicService.addToGrid(formValue);
    this.form.reset();
    this.router.navigate(['/grid']);
  }
}

表单组件模板



<div class="container">
    <h1> Add Records </h1>
    <form [formGroup]="form" (ngSubmit)="onSubmit(form.value)">
         <div class="form-group">
            <label> Title : </label> 
                <input type="text" class="form-control" required formControlName="title" placeholder="FirstName" [(ngModel)] ="title"> 
            </div>
            <div class="form-group">
                <label> Body : </label> 
                <input type="text" class="form-control" required formControlName="body" placeholder="LastName">
            </div>
            <input type="submit" class="btn btn-info" name="Submit" [disabled]="!form.valid">


    </form>

</div>


My code is here in Stackblitz

1 个答案:

答案 0 :(得分:1)

对于这种基本情况,在没有主题的情况下进行可能会容易得多。

服务

private _url: string = "/assets/data/employeesData.json";
public employees: Employee[];

constructor(private httpClient: HttpClient) {
   this.getEmployees();
}

addToGrid(emp: Employee) { 
   this.employees.push(emp); 
}

getEmployees() {
  return this.httpClient.get<Employee[]>(this._url)
    .subscribe(
      (employees:Employee[]) => this.employees = employees);

}

  • 删除主题及其使用的每个地方。
  • 添加员工时,只需将其添加到数组中即可。

组件

export class GridComponent implements OnInit{

  get employees(): Employee[]{
     return this._basicService.employees;
  }

  constructor( private _basicService: BasicServices) {
  }

  ngOnInit() {

  }

}
  • 使用吸气剂以确保组件始终获取阵列的最新版本。 Angular的内置更改检测功能会在数组更改时重新绑定模板,该模板将调用此getter。

注意:未检查语法。

此外,如果您想继续使用Subject,则可能需要BehaviorSubject。如果要在表单组件和网格组件之间路由,则使用Subject仅将值发送给任何 current 订阅者。因此,如果您在路由后订阅,则不会发出该值。使用BehaviorSubject会保留最后发出的值,然后将在订阅时提供该值。

我刚刚在这里进行了快速堆叠:https://stackblitz.com/edit/angular-no-subject-deborahk

我还将相同的示例添加到了stackblitz中,但是使用了有效的BehaviorSubject来代替Subject

这不是很漂亮,但是它显示两个链接以使用简单的getter(“无主题”)路由到该版本,并显示一个带有BehaviorSubject(“有主题”)的版本。请注意,如果将BehaviorSubject改回Subject,它将停止工作,因为它将不会收到通知。

更新

根据新信息,以下是一些注释/建议:

1)您无法更新JSON文件。因此,如果您正在从JSON文件中读取数据(看起来像您一样),则无法将数据更新回该文件中。看到此内容以确认:Is it possible to write data to a locally json file with nothing but angular?

2)导航到组件时,将对其进行初始化并执行其ngOnInit方法。

3)在页面的每个 中,您正在ngOnInit中调用this._basicService.getEmployees();。据我所知,此方法将重新读取您的JSON文件,因此将加载原始数据并覆盖您通过可观察对象进行和处理的所有更改。

4)如果您查看我提供的stackblitz,您会注意到在这个工作示例中,该服务保存了数据数组,因此组件不需要继续获取数据并丢失更新。

希望这会有所帮助。