Как заставить таблицу отображать добавленные данные без обновления вручную - PullRequest
0 голосов
/ 13 февраля 2020

Я создаю очень грубое приложение CRUD в Angular 5 (я впервые использую фреймворк). У меня все работает хорошо по большей части.

В таблице отображаются данные с локального json сервера, модал отображает форму и принимает данные после отправки. Тем не менее, новые данные не отображаются после отправки формы, если я не обновлю sh страницы вручную.

Я хочу, чтобы после нажатия кнопки «Добавить клиента» модальное окно закрылось, и в таблице отобразилась добавленная запись. Ниже приведен основной код для рассматриваемых областей. Я чувствую, что я прямо там, но я просто не могу получить последний штрих.

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация / информация.

home.component.ts

export class HomeComponent implements OnInit {
  display='none';
  showNew: Boolean = false;
  constructor(private http: Http) { }

  /*
    1. initiate the customers array
    2. data is fetched from local json server with data storage
    3. results stored in the customers array
    4. function called 

  */
  customers = [];
  fetchData = function() {
   this.http.get("http://localhost:5555/customers").subscribe(
     (res: Response) => {
       this.customers = res.json();
     }
   )

  }

  /* 
   1. Create object
   2. Create function to read form data
  */
  customerObj:object = {};

  addNewCustomer = function(customer) {
    this.customerObj = {
      "firstname": customer.firstname,
      "lastname": customer.lastname
    }
    this.http.post("http://localhost:5555/customers", this.customerObj).subscribe((res:Response) => {
      console.log(res);
      this.showNew = true;
    })
  }

  onCloseHandled(){
    this.display='none';
  }

  openModal(){
    this.display='block';
  }


  ngOnInit() {
    this.fetchData();
  }

}

home.component . html

<div class="container">
<h1>CUSTOMERS</h1>

<table class="table table-striped">
  <thead>
    <tr>
  <th>ID</th>
  <th>First Name</th>
  <th>Last Name</th>
</tr>
</thead>
<tbody>
  <tr *ngFor = "let customer of customers">
     <td>{{customer.id}}</td>
     <td>{{customer.firstname}}</td>
     <td>{{customer.lastname}}</td>
  </tr>
</tbody>
</table>
<br/>
<div class="text-left">
  <!-- open a modal window by clicking button-->
  <button type="submit" class="btn btn-primary" (click)="openModal()">New</button>
</div>
</div>




<!-- Modal for adding new customer -->
<div class="backdrop" [ngStyle]="{'display':display}"></div>

<div class="modal" tabindex="-1" role="dialog"  [ngStyle]="{'display':display}">

 <div class="modal-dialog" role="document">

   <div class="modal-content">

     <div class="modal-header">       

       <h4 class="modal-title">Add New Customer</h4>

     </div>

     <div class="modal-body">

       <form id = "formNewCustomer" name = "formNewCustomer" #customerData = "ngForm" (ngSubmit) = "addNewCustomer(customerData.value)">
          <label>First Name</label><input type ="text" name = "firstname" id = "firstname" placeholder="First Name" ngModel><br>
          <label>Last Name</label><input type ="text" name = "lastname" id = "lastname" placeholder="Last Name" ngModel><br>
          <input type="submit" value = "Add Customer">
        </form>


     </div>

     <div class="modal-footer">

       <button type="button" class="btn btn-danger" (click)="onCloseHandled()" >Close</button>

     </div>

   </div><!-- /.modal-content -->

 </div><!-- /.modal-dialog -->

</div><!-- /.modal !-->

Ответы [ 3 ]

0 голосов
/ 13 февраля 2020
// Just add this line this.fetchData();


    this.http.post("http://localhost:5555/customers", 
    this.customerObj).subscribe((res:Response) => {
        console.log(res);
        this.showNew = true;
        this.fetchData();
    })
0 голосов
/ 13 февраля 2020

Во-первых, в вашем *ngFor l oop необходимо добавить отслеживание:

  <tr *ngFor = "let customer of customers; trackBy: someTrackingFunction">

(Придумайте someTrackingFunction, например, он должен однозначно идентифицировать идентификатор клиента - объекта) .

Затем в своем сообщении вы можете просто добавить нового клиента в массив:

this.http.post("http://localhost:5555/customers", this.customerObj)
    .subscribe((res: Response) => {
        const newCustomer = // usually, in REST APIs, res will be the new customer object.

        this.customers = [...this.customers, newCustomer].sort(someOptionalSortingFunction);

Кстати, вам нужно вручную вызвать json() для объекта ответа? Это уже давно устарело. Почему бы не использовать (не новый) HttpClientModule?

0 голосов
/ 13 февраля 2020

Вам нужно будет повторно получить данные после добавления нового клиента.

Что-то вроде:

  addNewCustomer(customer) {
    const customerObj = {
      "firstname": customer.firstname,
      "lastname": customer.lastname
    };

    this.http
      .post("http://localhost:5555/customers", customerObj)
      .pipe(
        switchMap(() => this.fetchData())
      ).subscribe((res:Response) => {
        console.log(res);
        // not sure if this.showNew is required? leaving it in for completeness
        this.showNew = true;
      });
  }

Обратите внимание, как я повторно вызываю fetchMap изнутри switchMap. switchMap просто означает, что после возвращения первой наблюдаемой, переключитесь на новую наблюдаемую, прежде чем вернуться к телу подписки.

NB - вам не нужно использовать синтаксис function() в функциях класса.

Редактировать:

И вам потребуется рефакторинг вашего метода fetchData, если вы хотите использовать этот метод.

ngOnInit() {
    this.fetchData().subscribe();
}

// TODO: return array of interfaces, like Customer[]
fetchData(): Observable<[]> {
   return this.http
     .get("http://localhost:5555/customers")
     .pipe(
       // use map to transform the raw http response into a known type
       map(res => res.json())
       // use tap to assign the mapped response to a property
       tap(customers => this.customers = customers)
     );
}

Обычно вызовы http go в какой-то сервис, возвращающий наблюдаемые (не подписки). Затем вы должны подписаться на них в компонентах.

И вообще, лучше иметь дело с интерфейсами, а не передавать нагрузку json объектов вокруг. Вот для чего предназначен тип в машинописи;)

...