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, và 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.
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 –
@ 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
Bạn có bao giờ tìm ra điều này không? – DarkNeuron