привязка содержимого шаблона к наблюдаемой - PullRequest
0 голосов
/ 26 декабря 2018

У меня есть страница CRUD, и я хочу, чтобы она обновлялась при каждой сделанной операции.

Итак, я попытался использовать Observable, и все функции CRUD работают нормально (просто добавьте и удалите сейчас), но мне нужночтобы обновить страницу, чтобы увидеть изменения.

Я пытался вызвать функцию this.ngOnInit() в конце каждой операции, но ничего не получалось.

productmanagement.component.ts

import { Component, OnInit } from '@angular/core';
import { routerTransition } from '../../../router.animations';
import { Observable } from 'rxjs';
import { Category } from 'src/app/_models';
import { CategoryService } from './_services/category.service';

@Component({
    selector: 'app-productmanagement',
    templateUrl: './productmanagement.component.html',
    styleUrls: ['./productmanagement.component.scss'],
    animations: [routerTransition()],
    providers: [CategoryService]
})
export class ProductManagementComponent implements OnInit {

    public categorysObservable$: Observable<Category>;

    constructor(private categoryService: CategoryService) {}

    ngOnInit() {
        this.categorysObservable$ = this.categoryService.getAll();
    }

    categoryAdded(categoryname: string) {
        this.categoryService.add(categoryname);

    }

    deleteCategory(category: any) {
        this.categoryService.delete(category.idCategory);
    }
}

category.service.ts

@Injectable()
export class CategoryService {
    public categorysRequest: Observable<Category>;
    public categorySubject: Subject<Category>;

    constructor(private http: HttpClient) {
        this.categorySubject = new ReplaySubject(1);
    }

    getAll(refresh: boolean = false) {
        if (refresh || !this.categorysRequest) {
            this.categorysRequest = this.http.get<Category>(`http://localhost:5000/api/Category`);

            this.categorysRequest.subscribe(
                result => this.categorySubject.next(result),
                err => this.categorySubject.error(err)
              );
        }
        return this.categorySubject.asObservable();
    }

    getById(id: number) {
         return this.http.get(`http://localhost:5000/api/Category/` + id);
    }

    add(category: string) {
        return this.http.post<Category>('http://localhost:5000/api/Category', {Category: category}).subscribe();
    }

    update(category: Category) {
        return this.http.put(`http://localhost:5000/api/Category/` + category.idCategory, category);
    }

    delete(id: number) {
        return this.http.delete<any>(`http://localhost:5000/api/Category?id=` + id).subscribe();
    }
}

productmanagement.component.html

<!--Categorys-->
    <div *ngIf="(categorysObservable$ | async)">
        <div *ngFor="let category of (categorysObservable$ | async)">
            <div class="card">
                <div class="card-header">
                    <p style="display: inline" name='idCategory'> {{ category.category1 }} </p>

                    <button class='btn btn-danger' style="float: right;" (click)="deleteCategory(category)">delete</button>
                    <button class='btn btn-warning' style="float: right; margin-right: 10px;">edit</button>
                    <button class="btn btn-success" style="float: right; margin-right: 10px;">add Product</button>
                </div>
                <div *ngIf="category.product.length>0 else noProduct">
                    <table class="card-body table table-hover">
                        <thead>
                            <tr>
                                <th>Product</th>
                                <th>Reference</th>
                                <th>Serial Number</th>
                                <th>Price</th>
                                <th>quantity</th>
                                <th style="width: 165px"></th>
                            </tr>
                        </thead>
                        <tbody *ngFor="let prod of category.product">
                            <tr>
                                <td>{{ prod.product1 }}</td>
                                <td>{{ prod.reference }}</td>
                                <td>{{ prod.serialNumber }}</td>
                                <td>{{ prod.price }}</td>
                                <td>{{ prod.quantite }}</td>
                                <td>
                                    <button class='btn btn-outline-warning'>edit</button> &nbsp;
                                    <button class='btn btn-outline-danger'>delete</button>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
                <ng-template #noProduct class="align-content-center">
                    <br>
                    <p class='text-center'>No Poducts yet</p>
                </ng-template>
            </div>
            <br>
        </div>
    </div>

Включение this.ngOnInit() в компонент не помогло также использование AsyncPipe в шаблоне.Итак, я понимаю, что решение заключается в связывании наблюдаемого с шаблоном.

1 Ответ

0 голосов
/ 26 декабря 2018

Вы слишком усложняете вещи.Вам не нужно создавать другую Observable, если "http's" get() вернет Observable сама по себе.Если вы хотите отказаться от подписки, вы можете сделать это, когда ваш компонент разрушается.Если я правильно понимаю, то единственное преимущество добавления блока if() в getAll() - не вызывать другой HTTP-запрос, если он уже в пути.

Сделайте ваш getAll() следующим образом:

getAll() {
    this.http.get<Category>(`http://localhost:5000/api/Category`);
}

Создайте переменную класса в вашем компоненте, которая содержит подписку

getAllSubscription: Subscription

Создайте метод getAllCategories() в вашем компоненте.

Нет необходимости categorysObservable$prop в классе, вместо этого создайте categories prop, который содержит фактические данные.

getAllCategories() {
  if (this.getAllSubscription) {
    this.getAllSubscription.unsubscribe();
  }
  this.getAllSubscription = this.categoryService.getAll().subscribe((data) => {
    this.categories = data;
  }, (error) => {
      // errors will come here
  })
}

Удалите async pipe из вашего шаблона и используйте его вместо

<div *ngIf="categories">
    ....
</div>

Измените другие методы в вашем сервисе так, чтобы они просто возвращали Observable (не подписывайтесь туда), например:

add(category: string) {
    return this.http.post<Category>('http://localhost:5000/api/Category', {Category: category});
}

, вызов getAllCategories() для ваших categoryAdded() и deleteCategory() методов

categoryAdded(categoryname: string) {
    this.categoryService.add(categoryname).subscribe((data) => {
       // do something with data, show error success msgs,etc
       this.getAllCategories();
    })
}

Примечание: Могут быть и другие способы (с помощью rxjs операторов сглаживания) для достижения getAll() в update (), delete () Observables.Я использовал их как отдельные Наблюдаемые, полагая, что вам понадобятся отдельные ответы об успехах / ошибках для каждого из запросов.

Обновление

Если вам нужно использовать операторы сплющивания, выможет реализовать это следующим образом.

add(category: string) {
    return this.http.post<Category>('http://localhost:5000/api/Category', {Category: category}).pipe(
      mergeMap((dataFromAdd) => {
        // can just return this.getAll() if you don't care for the response of the above post() request. (But you should care!)
        return this.getAll().pipe(
          map((dataFromGetAll) => {
                return {
                  addResponse: dataFromAdd,
                  allCategories: dataFromGetAll
                }
            })
          )

      })
    )
}

В вашем компоненте измените categoryAdded() как

categoryAdded(categoryname: string) {
    this.categoryService.add(categoryname).subscribe((data) => {
       this.categories = data.allCategories
    })
}
...