IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

3. diel - Blazor - Binding

V predchádzajúcej lekcii, Blazor - Rozšírenie Todo aplikácie v .NET Core SPA , sme v našej Todo aplikácii pokračovali a ukázali si, ako správne reagovať na udalosti.

Dnes si uvedieme, čo je to vlastne binding a aká je výhoda two-way binding. Názorne si všetko ukážeme na ďalšom príklade webové aplikácie v Blazor a C# .NET.

Binding

Binding je v podstate väzba medzi premennou v kóde a jej využitím v HTML časti komponenty alebo v podriadenej komponente. Binding môže byť:

  • Jednosmerný - Jednosmerná väzba je užitočná, keď potrebujeme reprezentovať dáta v používateľskom rozhraní len na čítanie.
  • Obojsmerný - Obojsmerná väzba sa používa, ak potrebujeme aktualizovať stav komponentov pri zmene hodnoty premennej. Preto sa obvykle používa pri vstupných komponentov v HTML, kde zmena hodnoty užívateľom môže priamo ovplyvniť správanie ďalších komponentov alebo prvkov na stránke.

Príklad

Ako je binding implementovaný v Blazoru si pre lepšie pochopenie ukážeme na jednoduchom príklade. Budeme prevádzať užívateľom zadanú hodnotu z palcov na centimetre a obrátene. Vytvorme si novú stránku (teda komponent v zložke Pages/) s názvom Converter.

Ruta

Pretože sa jedná o stránku, nastavme ju hneď na prvom riadku route (s pomocou direktívy @page) pre definíciu relatívnej URL, na ktorej ju môžeme zobraziť:

@page "/converter"

Odkaz do menu

Aby sme nemuseli vyššie zadanú cestu písať v prehliadači ručne (aj keď si môžete vyskúšať, že to funguje), pridajme si na ňu odkaz do menu. To je jednoduchá úprava komponenty NavMenu. "Naklonujte" si blok <li>...</li> v zozname odkazov a upravme cieľ (href), ikonu (oi-...) a text odkazu:

<li class="nav-item px-3">
    <NavLink class="nav-link" href="converter">
        <span class="oi oi-transfer" aria-hidden="true"></span> Převodník
    </NavLink>
</li>

Po spustení aplikácie nám v menu pribudne odkaz na našu novú stránku:

Blazor - C # .NET namiesto JavaScriptu

Jednosmerný binding

Pridajme si do kódu stránky premennú palce typu double a do HTML vstupné pole a text, do ktorých bude jej hodnota nadviazaná:

<input value="@palce" type="number" />
<p>Hodnota v palcích je: @palce</p>
@code {
    double palce = 1;
}

Zamyslime sa nad tým, ako bude komponent fungovať. Je zrejmé, že po spustení by sa vo vstupnom poli mala objaviť východisková hodnota premennej (v našom prípade 1). Text pod vstupným poľom by mal byť "Hodnota v palcích je: 1".

Ale čo sa stane, keď vo vstupnom poli hodnotu zmeníme? Pre niekoho možno prekvapivo sa zmení práve len hodnotu vo vstupnom poli, ale nie v texte pod ním. Tento spôsob väzby je práve označovaný ako jednosmerná väzba. Jazykom programátorov by sme tiež mohli povedať, že sme do časti HTML odovzdali premennú palce nie referencií, ale hodnotou.

Reakcia na udalosť onchange

My samozrejme chceme, aby sa pri zmene hodnoty vo vstupnom poli zodpovedajúcim spôsobom zmenil aj text pod vstupným poľom. Musíme preto k jednosmernej väzbe pridať ešte reakciu na udalosť onchange vstupného poľa. Do tejto metódy môžeme pridať logiku, ktorá aktualizuje hodnotu v premennej palce:

void UpdateValue(ChangeEventArgs e)
{
    double val = 0;
    double.TryParse(e.Value.ToString(), out val);
    palce = val;
}

A túto metódu priradíme k udalosti onchange vstupného poľa:

<input value="@palce" type="number" @onchange="UpdateValue"/>

Môžeme vyskúšať, že po spustení aplikácie sa bude hodnota v texte automaticky aktualizovať podľa hodnoty vo vstupnom poli.

Obojsmerný binding

Ako vidíme, náš príklad je funkčný aj s jednosmernou väzbou spolu s ošetrením udalosti onchange. Existuje ale jednoduchší spôsob a tým je práve obojsmerná väzba.

Túto väzbu vytvoríme s pomocou direktívy @bind. Zaujímavé na našej predchádzajúcej implementáciu je, že funguje veľmi podobne ako interný implementácie @bind. Tá sa tiež defaultne viaže na atribút value, používa ako predvolené udalosť onchange, po jej vyvolaní aktualizuje hodnotu v naviazané premennej a pri tom ju automaticky prevádza na správny dátový typ.

S použitím obojsmerné väzby je samozrejme zápis kratšie a prehľadnejšie:

<input @bind="palce" type="number"/>
<p>Hodnota v palcích je: @palce</p>
@code {
    double palce = 1;
}

Pole pre centimetre

U obojsmerné väzby zostaneme a rozšírime komponent o ďalšie vstupné polia a príslušnú premennú pre centimetre. Zobrazovaný text môžeme už odstrániť:

<label>Palce</label>
<input type="number" @bind="palce" />
<span> = </span>
<input type="number" @bind="centimetry" />
<label>Centimetry</label>
@code {
double palce = 1;
double centimetry = 2.54;
}

Každý vstup je zviazaný so svojou premennou, ale chýba logika, ktorá pri zmene hodnoty jednej z premenných prepočíta a upraví tú druhú. K tomu môžeme použiť klasické properties zo C# a ich setter. Úprava pre prepočítanie hodnoty v centimetroch po zmene hodnoty v palcoch by mohla vyzerať nejako takto:

double palce = 1;
public double Palce
{
    get => palce;
    set
    {
        centimetry = value * 2.54;
        palce = value;
    }
}

Potom ale nesmieme zabudnúť na vstupné pole miesto premenné palce nadviazať vlastnosť Palce:

<input type="number" @bind="Palce" />

Prevod z palcov na centimetre by teraz mal fungovať. Ak obdobnú úpravu urobíme aj pre centimetre, naša jednoduchá komponent bude plne funkčný.

Ďalšie možnosti

Ako sme spomenuli vyššie, binding sa defaultne viaže na atribút value a používa ako predvolené udalosť onchange. Obe tieto vlastnosti väzby možno jednoducho upraviť.

Pre zmenu viazaného atribútu možno použiť namiesto skrátenej direktívy @bind="variable" tvar @bind-propertyName="variable". Napríklad nami použitý zápis @bind="Palce" by mohol mať tiež tvar @bind-value="Palce" s rovnakým významom.

Zmena predvolenej udalosti väzby sa vykoná pridaním ďalšieho parametra v tvare @bind-propertyName:event="eventName". Ak by sme teda v našom prípade chceli aktualizovať hodnotu premennej hneď po stlačení klávesy, nie až po opustení komponenty, použili by sme dlhší tvar direktívy @bind a pripísali by sme ďalšie parameter @bind-value:event="oninput".

Väzba na parameter podriadenej komponenty

Na samostatnom príklade si môžeme ukázať binding do podriadenej komponenty:

<h2>Child Component</h2>
<p>Year: @Year</p>
@code {
    [Parameter]
    public int Year { get; set; }

    [Parameter]
    public EventCallback<int> YearChanged { get; set; }
}

EventCallback<>

Ak chceme použiť binding do podriadenej komponenty, musí v nej byť okrem príslušnej public property tiež parameter typu EventCallback<...> s rovnakým dátovým typom.

Menná konvencie nám tiež dôrazne odporúča pomenovať tento druhý parameter rovnako ako prvý parameter s prídavkom Changed, tak ako vidíme na predchádzajúcom príklade - vlastnosť Year a príslušný EventCallback YearChanged. Ak túto konvenciu dodržíme, nemusíme pri použití komponenty druhý parameter vôbec špecifikovať a Blazor si ho priradí automaticky:

@page "/ParentComponent"

<h1>Parent Component</h1>

<p>ParentYear: @ParentYear</p>

<ChildComponent @bind-Year="ParentYear" />

<button class="btn btn-primary" @onclick="IncrementYear">
    Increment Year
</button>
@code {
    [Parameter]
    public int ParentYear { get; set; } = 1976;

    private void IncrementYear()
    {
        ParentYear++;
    }
}

Rodičovská komponenta

V rodičovskej komponente máme vlastnosť ParentYear, jej hodnotu nadviažeme na parameter Year podriadené komponenty (a ešte raz si ju zobrazíme priamo v tejto komponente). Po kliknutí na tlačidlo zmeníme v rodičovskej komponente hodnotu ParentYear a v prehliadači uvidíme, že zmena nastane tak v priamom zobrazenie, tak v podriadenej komponente.

Zmena v rodičovskej komponente

Až potiaľto všetko funguje dobre. Problém nastane, ak by sme vnútri podriadenej komponenty chceli hodnotu naviazaného parametra Year meniť. Takzvané zreťazenie väzieb bohužiaľ nefunguje, takže ak by sme aj vo vnútri podriadené komponenty použili obojsmerný binding na nejaké vstupné pole <input type="number" @bind="Year" />, o zmene hodnoty sa rodičovská komponent nedozvie. To možno našťastie obísť použitím jednosmernej väzby a vyvolaním udalosti podobne ako na začiatku dnešnej lekcie:

<h2>Child Component</h2>

<input type="number" value="@Year" @onchange="OnYearChanged" />
@code {
    [Parameter]
    public int Year { get; set; }

    [Parameter]
    public EventCallback<int> YearChanged { get; set; }

    private void OnYearChanged(ChangeEventArgs e)
    {
        int year = Year;
        int.TryParse(e.Value.ToString(), out year);
        if (year != Year)
        {
            Year = year;
            YearChanged.InvokeAsync(year);
        }
    }
}

Teraz by mal fungovať binding z rodičovskej komponenty do podriadenej aj obrátene:-)

To je pre túto lekciu všetko. Nabudúce sa pozrieme podrobnejšie na komponenty. Námety na ďalšie lekcie môžete písať do komentárov;-)

V ďalšej lekcii, Blazor - Komponenty , sa podrobnejšie pozrieme na komponenty a možnosti, ktoré nám ponúka parametre.


 

Predchádzajúci článok
Blazor - Rozšírenie Todo aplikácie v .NET Core SPA
Všetky články v sekcii
Blazor - C # .NET namiesto JavaScriptu
Preskočiť článok
(neodporúčame)
Blazor - Komponenty
Článok pre vás napísal JOF
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Aktivity