Zacząłem patrząc na coś takiego zintegrowania kontroli formularzy z mojej biblioteki ng-app-state. Jeśli jesteś typem, który lubi tworzyć bardzo ogólny, podobny do biblioteki kod, czytaj dalej. Ale uwaga, to jest długie! W końcu powinieneś być w stanie wykorzystać to w swoich szablonach:
<input [subjectModel]="subject">
Zrobiłem proof-of-concept dla pierwszej połowie tej odpowiedzi, a druga połowa wierzę, jest poprawna, ale ostrzegamy że żaden z rzeczywistych kodów napisanych w tej odpowiedzi nie jest testowany. Przykro mi, ale to najlepsze, co mam teraz do zaoferowania. :)
Możesz napisać własną dyrektywę o nazwie subjectModel
, aby połączyć temat ze składnikiem formularza. Poniżej znajdują się podstawowe części, minus rzeczy takie jak czyszczenie. Bazuje on na interfejsie ControlValueAccessor
, więc Angular zawiera niezbędne adaptery do podłączenia do wszystkich standardowych elementów formularzy HTML: i będzie działał z dowolnymi niestandardowymi formantami, które znajdziesz w środowisku naturalnym, o ile używają one ControlValueAccessor
(która jest zalecaną praktyką).
@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);
});
}
}
Mogliśmy zatrzymać tutaj, a będziesz w stanie napisać to w szablonach:
<input [subjectModel]="subject" [ngDefaultControl]>
To dodatkowy [ngDefaultControl]
istnieje ręcznie spowodować kątowe, aby zapewnić wymaganą ControlValueAccessor
do naszej dyrektywy. Inne rodzaje danych wejściowych (takie jak przyciski i wybory) wymagałyby innej dodatkowej dyrektywy. Wynika to z faktu, że Angular nie dołącza automatycznie wartości dodawanych do każdego komponentu formularza, tylko te, które mają także ngModel
, formControl
lub formControlName
.
Jeśli chcesz zrobić więcej, aby wyeliminować potrzebę stosowania tych dodatkowych dyrektyw, musisz zasadniczo skopiować je do kodu, ale zmodyfikuj selektory, aby aktywować dla nowego subjectModel
. Jest to całkowicie niesprawdzone część, ale wierzę, że można to zrobić:
// 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 {}
kredytowych dla mojego rozumienia tego idzie do ngrx-forms, która zatrudnia tej techniki.
Czego oczekujesz, gdy zmieni się wartość sygnału wejściowego? "Przedmiot" jest jednokierunkowy. '[ngModel] =" subject | async "(ngModelChange) =" subject.next ($ event) "' może działać –
@ GünterZöchbauer ['Subject'] (http://reactivex.io/rxjs/class/es6/Subject.js~Subject.html) jest dwukierunkowe. ['Observer'] (http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObserverDoc.html) i [' Observable'] (http://reactivex.io/rxjs/class/es6/ Observable.js ~ Observable.html). Nie przeszkadza mi też to, że to zawsze "BehaviorSubject" (http://reactivex.io/rxjs/class/es6/BehaviorSubject.js~BehaviorSubject.html), jeśli pomaga (ponieważ ma to metodę dostępu do bieżącej wartości) – mhelvens
Czy kiedykolwiek to rozgryzłeś? – DarkNeuron