将模板内容绑定到Observable

时间:2018-12-26 11:53:06

标签: angular typescript asp.net-core rxjs observable

我有一个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。因此,我认为解决方案是通过将Observable与模板绑定。

1 个答案:

答案 0 :(得分:1)

您太复杂了。如果“ http's” get()本身将返回一个Observable,则无需创建另一个Observable。如果要取消订阅,可以在组件销毁时执行。如果我理解它是正确的,那么在if()中添加getAll()块的唯一目的就是不要调用另一个HTTP请求(如果已经在路上)。

将您的getAll()设置为:

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

在包含订阅的组件中创建一个类变量

getAllSubscription: Subscription

在组件中使用getAllCategories()方法。

在课堂上不需要categorysObservable$道具,而是制作一个categories道具来保存实际数据。

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

从模板中删除async管道,并使用它

<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展平运算符)在update()和delete()Observables本身中实现getAll()。我将它们用作单独的Observable,认为您需要从每个请求中获得单独的成功/错误响应。

更新

如果必须使用展平运算符,则可以通过这种方式实现。

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
    })
}