Angular和rxjs子类用于状态管理

时间:2018-10-11 17:13:47

标签: angular rxjs

我只是想知道是否可以在服务中使用Subject来通知组件状态已更改。让我举个例子吧。 例如。我有一个组件adresses-list.component.ts 这只是地址列表。单击确定的地址后,其完整信息将在列表的右侧或模式中显示。它 将被称为“ edit-address.component.ts” 因此,用户可以在该组件中编辑地址并保存更改。 我当然知道,将会有一个后端要求对其进行更新。 但是,问题是我的adresses-list.component.ts不会知道此更改,因为它已订阅可观察的地址,而不是更改。 所以我的问题是: 这是正常的做法吗 在我的service.ts中:

addressesUpdated = new Subject();
editAddressById(id) {
// send info to DB
  return this.http.patch().map(_ => {this.addressesUpdated.next())
}

在我的addresses-list.component.ts

service.addressesUpdated.switchMap( _ => service.getAddresses())
.subscribe(...save data here)

在我看来,有一个更好的解决方案和一个更愚蠢的解决方案,但我不知道如何做得更好。

2 个答案:

答案 0 :(得分:2)

嗯,您当然可以做到。 Angular的EventEmitter也是(https://angular.io/api/core/EventEmitter)下的主题。但是,如果您觉得需要更频繁地执行此操作,我建议您查看一种状态管理解决方案,例如ngrx store:https://github.com/ngrx/platform

答案 1 :(得分:0)

使用Angular的方法是使用@Output EventEmitter进行双向模型绑定。您用于编辑地址的子组件是否从选择器标签上的attr绑定获取其视图模型?如果是这样,那么您就到了一半。这就是我要实现的目标的方式。

模型

export class AddressModel {
    public Street1: string;
    public Street2: string;
    public City: string;
    public StateProvince: string;
    public PostalCode: string;
    public CountryCode: string;
}

export class ApiResponse {
    public Success: boolean;
    public ErrorMessage: string;
}

父组件

@Component({
    selector: 'addressListComponent',
    templateUrl: './addressList.html';
})

export class AddressListComponent implements OnInit {
    addressList: AddressModel[];
    addressSelected: boolean[];

    constructor(private api: AddressApi){}

    ngOnInit(): void {
        this.AddressList = new AddressList();
        this.api.GetAddressList()
            .then(response: AddressModel[] => {
                this.addressList = response.slice(0);
                this.addressList.forEach(addr => {
                    this.addressSelected.push(false);
                });
            });
    }
}

父视图

<div class="card" *NgFor="let address of addressList; let i = "index"; [attr.data-index]="i" (click)="addressSelected[i]=!addressSelected[i]">
    <div class="card-body">
        <label>{{address.Street1}}</label>
        <label>{{address.Street2}}</label>
        <label>{{address.City}}</label>
        <label>{{address.StateProvince}}</label>
        <label>{{address.PostalCode}}</label>
        <label>{{address.Country}}</label>
    </div>
    <editAddressComponent *ngIf="addressSelected[i]" [(addressModel)]="addressList[i]"></editAddressComponent>
</div>

编辑地址子组件

@Component({
    selector: 'editAddressComponent',
    templateUrl: './editAddress.html'
})

export class EditAddressComponent {
    @Input() addressModel: AddressModel;
    @Output() addressModelChanged: EventEmitter<AddressModel> = new EventEmitter<AddressModel>();

    constructor(private api: AddressApi) { }

    saveChanges(): void {
        this.api.saveAddressChanges(this.addressModel)
            .then(response: ApiResponse => {
                if (response.Success === true) {
                    this.addressModelChanged.emit(this.addressModel);
                } else {
                    alert(response.ErrorMessage);
                }
            });
    }
}

子级编辑地址视图

<div class="card">
    <div class="card-body">
        <input [(ngModel)]="addressModel.Street1"/>
        <input [(ngModel)]="addressModel.Street2"/>
        <input [(ngModel)]="addressModel.City"/>
        <input [(ngModel)]="addressModel.StateProvince"/>
        <input [(ngModel)]="addressModel.PostalCode"/>
        <input [(ngModel)]="addressModel.Country"/>
        <button (click)="saveChanges()"></button>
    </div>
</div>

请注意父视图上的[()]语法。这就是魔术发生的地方。当您在组件上具有自定义@Input attr并通过[]向其传递值时,这是一种绑定方式。

如果像我对[()]所做的那样将自定义属性包装在addressModel中,则它是

的简写
<editAddressComponent [addressModel]="addressList[i]" (addressModelChanged)="addressList[i] = $event;"></editAddressComponent>

这意味着,在后台Angular正在设置您的子组件以支持事件发射器,这就是()模板语法所表示的。

参加

<button (click)="doStuff();"></button>

例如。

()表示一个eventEmitter,您要为其分配发射事件时要执行的操作,在这种情况下,请执行doStuff()方法。

因此使用

<editAddressComponent [(addressModel)]="addressList[i]"></editAddressComponent>

您正在设置子组件以支持EventEmitter,现在只需要制作一个即可。

这就是@Output所做的。它正在子组件中注册一个EventEmitter类型的可用变量,该变量专门发出一个AddressModel对象。

现在,当用户保存更改时,如果更改成功保存,则使用EventEmitter发出一个事件,该事件将更改后的addressModel作为要捕获的对象。

然后在父组件中捕获对象,并将其分配给索引i处的addressList。这将使您的父组件视图与子组件所做的更改保持同步。

相关问题