2016-07-29 23 views
22

Có cách nào ngắn và đơn giản để chuyển RxJS Subject hoặc BehaviorSubject tới chỉ thị Angular 2 cho liên kết hai chiều không? Các chặng đường dài để làm điều đó sẽ như sau:Làm cách nào để liên kết hai chiều RxJS của tôi với một [(ngModel)]?

@Component({ 
    template: ` 
     <input type="text" [ngModel]="subject | async" (ngModelChange)="subject.next($event)" /> 
    ` 
}) 

Tôi muốn để có thể làm điều gì đó như thế này:

@Component({ 
    template: ` 
     <input type="text" [(ngModel)]="subject" /> 
    ` 
}) 

tôi tin rằng các ống async chỉ là một chiều, vì vậy Như thế là không đủ. Angular 2 có cung cấp một cách đơn giản và ngắn gọn để làm điều này không? Angular 2 cũng sử dụng RxJS, vì vậy tôi mong đợi có một số khả năng tương thích vốn có.

Tôi có thể tạo một chỉ thị ngModel giống như mới để làm điều này có thể không?

+1

Bạn mong đợi điều gì sẽ xảy ra khi giá trị của đầu vào thay đổi? 'Subject' là một chiều. '[ngModel] =" chủ đề | async "(ngModelChange) =" chủ đề.tiếp theo ($ event) "' có thể làm việc –

+2

@ GünterZöchbauer ['Subject'] (http://reactivex.io/rxjs/class/es6/Subject.js~Subject.html) là hai chiều, mặc dù. ['Observer'] (http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObserverDoc.html) và một [' Observable'] (http://reactivex.io/rxjs/class/es6/ Tôi cũng ổn với điều này luôn luôn là một ['BehaviorSubject'] (http://reactivex.io/rxjs/class/es6/BehaviorSubject.js~BehaviorSubject.html), nếu nó (bởi vì có một phương pháp để truy cập vào giá trị hiện tại) – mhelvens

+0

Bạn có bao giờ tìm ra điều này không? – DarkNeuron

Trả lời

1

Gần nhất tôi có thể nghĩ đến là sử dụng một FormControl:

import { FormControl } from '@angular/forms'; 

@Component({ 
    template: '<input [formControl]="control">' 
}) 
class MyComponent { 
    control = new FormControl(''); 
    constructor(){ 
     this.control.valueChanges.subscribe(()=> console.log('tada')) 
    } 
} 
1

Tôi đã bắt đầu nhìn vào một cái gì đó như thế này để tích hợp điều khiển biểu mẫu với thư viện của tôi ng-app-state. Nếu bạn là loại người thích làm mã chung, giống như thư viện thì hãy đọc tiếp. Nhưng hãy cẩn thận, điều này là dài! Cuối cùng, bạn sẽ có thể sử dụng điều này trong các mẫu của mình:

<input [subjectModel]="subject"> 

Tôi đã thực hiện bằng chứng về khái niệm trong nửa đầu của câu trả lời này và nửa sau tôi tin là chính xác nhưng được cảnh báo rằng không có mã thực tế nào được viết trong câu trả lời này được kiểm tra. Tôi xin lỗi, nhưng đó là điều tốt nhất tôi phải cung cấp ngay bây giờ. :)

Bạn có thể viết chỉ thị của riêng bạn được gọi là subjectModel để kết nối chủ thể với thành phần biểu mẫu. Sau đây là những phần thiết yếu, trừ đi những thứ như dọn dẹp. Nó dựa trên giao diện ControlValueAccessor, do đó Angular bao gồm các bộ điều hợp cần thiết để móc điều này lên tất cả các phần tử biểu mẫu HTML chuẩn, nó sẽ hoạt động với bất kỳ điều khiển biểu mẫu tùy chỉnh nào bạn tìm thấy trong tự nhiên, miễn là chúng sử dụng ControlValueAccessor (là phương pháp được khuyến nghị).

@Directive({ selector: '[subjectModel]' }) 
export class SubjectModelDirective { 
    private valueAccesor: ControlValueAccessor; 

    constructor(
     @Self() @Inject(NG_VALUE_ACCESSOR) 
     valueAccessors: ControlValueAccessor[], 
    ) { 
     this.valueAccessor = valueAccessors[0]; // <- this can be fancier 
    } 

    @Input() set subjectModel(subject: Subject) { 
     // <-- cleanup here if this was already set before 
     subject.subscribe((newValue) => { 
      // <-- skip if this is already the value 
      this.valueAccessor.writeValue(newValue); 
     }); 
     this.valueAccessor.registerOnChange((newValue) => { 
      subject.next(newValue); 
     }); 
    } 
} 

Chúng ta có thể dừng lại ở đây, và bạn sẽ có thể viết những dòng này trong các mẫu của bạn:

<input [subjectModel]="subject" [ngDefaultControl]> 

Đó thêm [ngDefaultControl] tồn tại tự gây ra góc để cung cấp cần thiết ControlValueAccessor để chỉ thị của chúng tôi. Các loại đầu vào khác (như nút radio và lựa chọn) sẽ cần một chỉ thị bổ sung khác. Điều này là do Angular không tự động gắn các giá trị truy cập vào mọi thành phần biểu mẫu, chỉ những người có cũng có một ngModel, formControl hoặc formControlName.

Nếu bạn muốn đi thêm dặm để loại bỏ nhu cầu cho các chỉ thị bổ sung đó, bạn sẽ phải sao chép chúng vào mã của mình, nhưng sửa đổi bộ chọn của chúng để kích hoạt subjectModel mới. Đây là phần hoàn toàn chưa được kiểm tra, nhưng tôi tin rằng bạn có thể làm điều này:

// This is copy-paste-tweaked from 
// https://angular.io/api/forms/DefaultValueAccessor 
@Directive({ 
    selector: 'input:not([type=checkbox])[subjectModel],textarea[subjectModel]', 
    host: { 
     '(input)': '_handleInput($event.target.value)', 
     '(blur)': 'onTouched()', 
     '(compositionstart)': '_compositionStart()', 
     '(compositionend)': '_compositionEnd($event.target.value)' 
    }, 
    providers: [DEFAULT_VALUE_ACCESSOR] 
}) 
export class DefaultSubjectModelValueAccessor extends DefaultValueAccessor {} 

tín dụng cho sự hiểu biết của tôi về điều này đi đến ngrx-forms, mà employes kỹ thuật này.

+0

Có vẻ thú vị. Là giải pháp này có sẵn trở lại khi tôi lần đầu tiên hỏi câu hỏi? --- Tôi sợ tôi sẽ không có thời gian để xác minh điều này. Tôi sử dụng React trong công việc mới của tôi, và tâm trí của tôi thực sự không có trong không gian góc ngay bây giờ. --- Nếu ai đó có thể xác minh, tôi sẽ vui lòng chấp nhận câu trả lời. – mhelvens

+0

Tôi không chắc chắn khi nào điều này có thể trở thành có thể. –

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