ich angefangen habe, einen Blick in so etwas wie diese ng-app-state Formular-Steuerelemente mit meiner Bibliothek zu integrieren. Wenn Sie der Typ sind, der gerne generischen, bibliotheksähnlichen Code erstellt, dann lesen Sie weiter. Aber Vorsicht, das ist lang! Am Ende sollten Sie in der Lage sein, dies in Ihre Templates zu verwenden:
<input [subjectModel]="subject">
ich ein Proof-of-Concept für die erste Hälfte dieser Antwort gemacht haben, und die zweite Hälfte glaube ich, ist richtig, aber seien Sie gewarnt, dass keiner der tatsächlichen Codes in dieser Antwort getestet wird. Es tut mir leid, aber das ist das Beste, was ich jetzt zu bieten habe. :)
Sie können Ihre eigene Direktive namens subjectModel
schreiben, um einen Betreff mit einer Formularkomponente zu verbinden. Im Folgenden sind die wesentlichen Teile, minus Dinge wie Aufräumen. Es stützt sich auf die ControlValueAccessor
Schnittstelle, also schließt Winkel die notwendigen Adapter ein, um dieses bis zu allen StandardHTML Formularelementen, und anzubringen es funktioniert mit allen möglichen Formsteuerungen, die Sie im wilden finden, solange sie ControlValueAccessor
benutzen (das ist die empfohlene Praxis).
@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);
});
}
}
Wir könnten hier aufhören, und Sie werden diese in der Lage sein, in die Vorlagen zu schreiben:
<input [subjectModel]="subject" [ngDefaultControl]>
Das zusätzliche [ngDefaultControl]
die benötigte ControlValueAccessor
zu unserer Richtlinie zu schaffen Winkel manuell verursachen vorhanden ist. Andere Arten von Eingängen (wie Radio-Buttons und Selects) würden eine andere Extra-Direktive benötigen. Dies liegt daran, dass Angular nicht automatisch Wert-Accessoren an jede Formularkomponente anfügt, sondern nur an diejenigen, die auch eine ngModel
, formControl
oder formControlName
haben.
Wenn Sie die Extra-Meile nutzen möchten, um die zusätzlichen Anweisungen zu umgehen, müssen Sie sie im Wesentlichen in Ihren Code kopieren, aber ihre Selektoren ändern, um sie für Ihre neue subjectModel
zu aktivieren. Dies ist das völlig ungetestet Teil, aber ich glaube, dass Sie dies tun könnte:
// 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 {}
Kredit für mein Verständnis davon geht zu ngrx-forms, die diese Technik employes.
Was erwarten Sie, wenn sich der Wert des Eingangs ändert? "Subject" ist in eine Richtung. '[ngModel] =" subject | async "(ngModelChange) =" subject.next ($ event) "' könnte funktionieren –
@ GünterZöchbauer ['Subject'] (http://reactivex.io/rxjs/class/es6/Subject.js~Subject.html) ist zwei-Wege, obwohl. Es ist sowohl ein ['Observer] (http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObserverDoc.html) und ein [' Observable'] (http://reactivex.io/rxjs/class/es6/ Observable.js ~ Observable.html) Ich bin auch damit einverstanden, dass dies immer ein ['BehaviorSubject'] ist (http://reactivex.io/rxjs/class/es6/BehaviorSubject.js~BehaviorSubject.html), wenn es so ist hilft (weil das eine Methode hat, auf den aktuellen Wert zuzugreifen) – mhelvens
Haben Sie das jemals herausgefunden? – DarkNeuron