2017-02-19 17 views
6

Kế hoạch của tôi là lưu trữ các giá trị của biểu mẫu trong cửa hàng ngrx của tôi để cho phép người dùng của tôi điều hướng xung quanh trang web và quay lại biểu mẫu nếu họ muốn. Ý tưởng sẽ là các giá trị của biểu mẫu sẽ trở lại từ cửa hàng bằng cách sử dụng một quan sát được.Làm thế nào tôi có thể khởi tạo một dạng Angular2 phản ứng bằng cách sử dụng một Observable?

đây là làm thế nào tôi đang làm nó hiện:

constructor(private store: Store<AppState>, private fb: FormBuilder) { 
    this.images = images; 
    this.recipe$ = store.select(recipeBuilderSelector); 
    this.recipe$.subscribe(recipe => this.recipe = recipe); // console.log() => undefined 
    this.recipeForm = fb.group({ 
     foodName: [this.recipe.name], // also tried with an OR: (this.recipe.name || '') 
     description: [this.recipe.description] 
    }) 
    } 

Các cửa hàng được đưa ra một giá trị ban đầu mà tôi đã thấy qua chức năng chọn của tôi đúng, nhưng theo thời gian các hình thức của tôi được tạo ra, tôi don không nghĩ rằng giá trị đã trở lại. Do đó, this.recipe vẫn chưa được xác định.

Đây có phải là cách tiếp cận sai, hoặc bằng cách nào đó tôi có thể đảm bảo rằng có thể quan sát được trước khi tạo biểu mẫu?

Trả lời

3

tôi có thể nghĩ đến hai lựa chọn ...

Lựa chọn 1:

Sử dụng một *ngIf trên html hiển thị dưới dạng một cái gì đó giống như

<form *ngIf="this.recipe">...</form> 

Phương án 2: Sử dụng đường ống async trong mẫu của bạn và tạo mô hình của bạn như:

phần

model: Observable<FormGroup>;  
... 
this.model = store.select(recipeBuilderSelector) 
    .startWith(someDefaultValue) 
    .map((recipe: Recipe) => { 
     return fb.group({ 
      foodName: [recipe.name], 
      description: [recipe.description] 
     }) 
    }) 

mẫu

<app-my-form [model]="(model | async)"></app-my-form> 

Bạn sẽ phải xem xét làm thế nào để xử lý các bản cập nhật cho các cửa hàng và các mô hình hiện tại.

+1

Tôi không thể làm cho nó hoạt động theo cách này. 'startsWith() không tồn tại trên kiểu Observable'. chức năng đó dường như chỉ tồn tại cho các chuỗi. –

+0

Tôi xin lỗi, phương thức phải là 'startWith'. https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/startwith.md – shusson

+0

'.startWith()' làm việc trên lần lặp đầu tiên, nhưng khi lần thứ hai (chế độ dev) chạy nó lại không xác định. Tôi đã làm cho nó hoạt động bằng cách loại bỏ 'startWith()' và thay đổi bộ chọn của tôi thành: 'return _.cloneDeep (state.recipebuilder) || someDefaultValue; ' –

5

Mặc dù việc thêm lớp khác có vẻ phức tạp hơn, nó là dễ dàng hơn nhiều để đối phó với quan sát thông qua việc tách các thành phần đơn lẻ thành hai: một chứa phần và một presentational phần.

Thành phần vùng chứa chỉ giao dịch với các quan sát chứ không phải với bản trình bày. Các dữ liệu từ bất kỳ quan sát được chuyển cho các thành phần trình bày qua @Input tài sản và các đường ống async được sử dụng:

@Component({ 
    selector: "recipe-container", 
    template: `<recipe-component [recipe]="recipe$ | async"></recipe-component>` 
}) 
export class RecipeContainer { 

    public recipe$: Observable<any>; 

    constructor(private store: Store<AppState>) { 
    this.recipe$ = store.select(recipeBuilderSelector); 
    } 
} 

Thành phần presentational nhận tính đơn giản và không phải đối phó với quan sát:

@Component({ 
    changeDetection: ChangeDetectionStrategy.OnPush, 
    selector: "recipe-component", 
    template: `...` 
}) 
export class RecipeComponent { 

    public recipeForm: FormGroup; 

    constructor(private formBuilder: FormBuilder) { 
    this.recipeForm = this.formBuilder.group({ 
     foodName: [""], 
     description: [""] 
    }); 
    } 

    @Input() set recipe(value: any) { 
    this.recipeForm.patchValue({ 
     foodName: value.name, 
     description: value.description 
    }); 
    } 
} 

Khái niệm sử dụng các thành phần container và presentational là một khái niệm Redux chung và được giải thích trong Presentational and Container Components.

+0

Tôi không thể có được cách này để làm việc cho tôi. Bằng cách nào đó hình thức đã được xây dựng trước khi Selector được gọi là –

+0

Vâng, tôi thấy quan điểm của bạn. Tôi đã tạo biểu mẫu trong hàm tạo và chỉ áp dụng các thay đổi khi '@ Input' được thay đổi. Tôi đã cập nhật câu trả lời. Cho dù bạn quyết định đi theo cách nào, tôi khuyên bạn nên xem xét việc tách những thứ thành các thành phần chứa đựng và các thành phần thuyết trình, vì nó làm cho cuộc sống dễ dàng hơn. – cartant

+0

bất kỳ lời chỉ trích hoặc lựa chọn của shusson 2 câu trả lời? Tôi đã có thể làm điều đó mà không có một thùng chứa bằng cách sử dụng '[formGroup] =" recipe $ | async "' –

Các vấn đề liên quan