Kontrolki wartości
Źródło:
ValueView.js
Każda kontrolka silnika dziedziczy po ValueView i spełnia jeden kontrakt wartości: tak samo oddaje wartość, tak samo ją przyjmuje i tak samo zapisuje ją do VarStore. Dzięki temu formularz, tabela i akcja nie muszą wiedzieć, czy pod id kryje się pole tekstowe, suwak czy grupa checkboxów.
Publiczne API
const view = document.querySelector('[data-view-id="customerName"]');
view.getValue(); // wartość z zachowaniem typu
view.setValue('Jan Kowalski'); // ustawia wartość, NIE uruchamia onChange
view.setValue('Jan Kowalski', { emitChange: true }); // ustawia wartość i uruchamia onChange
setValue() zwraca wartość, która faktycznie została zapisana, i nigdy nie rzuca błędem. Z tego samego API korzysta akcja setValue, więc schemat nie musi sięgać do wewnętrznego DOM-u widoku.
Zasady
- Stan jest źródłem prawdy, DOM tylko go reprezentuje. Wartość początkowa,
setValue()i zmiana użytkownika trafiają natychmiast doVarStore, więcwithDatanie musi czytać DOM-u ani czekać na interakcję. - Wartości zachowują typy. Podklasa konwertuje wartość w
normalizeValue()— liczba pozostaje liczbą, checkbox booleanem, wybór wielokrotny tablicą. emitChangedomyślniefalse. Programowa zmiana wartości nie uruchamiaonChange, co chroni przed przypadkowymi pętlami akcji.- Wartość spoza dozwolonego zbioru jest odrzucana. Po wyrenderowaniu
setValue()odczytuje przezreadbackValue()wartość przyjętą przez kontrolkę i to ona trafia do stanu: nieistniejąca opcja czyści wybór, aslideristepperprzycinają wartość do zakresumin–maxi wyrównują dostep. Store nigdy nie pokazuje czegoś innego niż UI. - Po odmontowaniu kontrolka przestaje pisać do store. Zapytanie o opcje rozwiązane po usunięciu widoku nie wskrzesi jego danych w
VarStore.
Kontrolki
| Widok | Wartość w VarStore | Wartość domyślna |
|---|---|---|
input | String, a przy inputType: number liczba (wartość pusta lub niepoprawna: '') | '' |
textinput | String (textarea) | '' |
select | String, a przy multiple: true tablica stringów | '' / [] |
checkbox | Boolean ("true" / "1" z templatki liczą się jako zaznaczenie) | false |
radiogroup | Wartość zaznaczonej opcji albo null | null |
checkboxgroup | Tablica wartości zaznaczonych opcji | [] |
slider | Liczba z zakresu min–max, wyrównana do step | min (domyślnie 0) |
stepper | Liczba z zakresu min–max, wyrównana do step | min, a bez min — 0 |
filepicker | File albo tablica File; mode: base64 daje deskryptor { name, mimeType, size, contentBase64 } | null / [] |
camera | Tablica zdjęć { name, mimeType, width, height, contentBase64 } | [] |
Kontrolki tablicowe (select z multiple, checkboxgroup, filepicker, camera) oddają w getValue() kopię tablicy, więc odbiorca nie modyfikuje stanu kontrolki.
Stan kontra operacja — onChange i onDelta
onChange odpowiada na pytanie jaka jest wartość — uruchamia się po zmianie użytkownika i respektuje debounce, więc kilka szybkich kliknięć daje jedno przeładowanie listy. W zakresie akcji dostępne jest {{ $value }} oraz — z zachowaniem typu — valueFrom: $value.
stepper dokłada do tego onDelta, które odpowiada na pytanie o ile się zmieniła — uruchamia się natychmiast i widzi w zakresie akcji $delta oraz $direction:
type: stepper
id: qty
label: Ilość
min: 1
max: 20
unit: szt.
onDelta:
action: callMethod
module: core/cart
method: adjust
params:
productId: "{{ $props.id }}"
delta:
valueFrom: $delta
Programowa zmiana wartości (setValue(), akcja setValue) nie uruchamia ani onChange, ani onDelta.
Jak dodać nową kontrolkę
Dziedzicz po ValueView, zbuduj DOM w _build(), na końcu wywołaj this.initValue(), a zmiany pochodzące od użytkownika przekazuj przez this.commitUserValue(value). Reszta kontraktu — zapis do VarStore, debounce, onChange — dzieje się sama.
| Punkt rozszerzenia | Rola | Domyślnie |
|---|---|---|
defaultValue() | Wartość, gdy schemat nie podaje value | null |
normalizeValue(value) | Konwersja do typu kontrolki | Bez zmian |
renderValue(value) | Zapis wartości do DOM kontrolki | Nic nie robi |
readbackValue(value) | Wartość faktycznie przyjęta przez kontrolkę | Bez zmian |
storeValue(value) | Publiczna postać wartości (getValue(), VarStore) | Bez zmian |
renderValue() działa w trybie „render”, w którym commitUserValue() jest ignorowane — kontrolka emitująca własne zdarzenie change przy programowej zmianie (np. TomSelect) nie uruchomi onChange mimo emitChange: false.
Powiązane: Dostępne Akcje (ActionHandler) · Zmienne (VarStore) · Edycja danych · Warianty stylistyczne
