Binding in Blazor
Inleiding
We hebben in eerdere posts aan een WebAssembly Blazor project functionaliteiten toegevoegd. Zo hebben we aan een project iets toegevoegd voor het kunnen toevoegen van gegevens en we hebben iets toegevoegd voor het getoond doen krijgen van gegevens. De functionaliteiten hebben we in Blazor gedefinieerd als componenten.
Zo zijn er componenten die een gebruikerscherm hebben en waarnaar genavigeerd moet worden vanuit een menubalk, maar er zijn ook componenten die deel uitmaken van een ander component (subcomponenten) en waar niet direct naar genavigeerd hoeft te worden.
Subcomponenten hebben op één of andere manier interactie met de hoofdcomponent en omgekeerd. Ze zijn met elkaar verbonden (binding) waarbij er twee vormen van binding zijn (One-way binding en Two-way binding). In deze post zullen we de bindingsvormen nader bekijken aan de hand van een ASP .NET Core hosted Blazor WebAssembly App en de voorbeeldcode kun je hier (GitHub) vinden.
Binding
We hebben in een eerder voorbeeld met Visual Studio een ASP .NET Core hosted Blazor WebAssembly App gecreëerd waarbij we voor de creatie gebruik hebben gemaakt van de aanwezige Blazor project templates. We gaan het één en ander toelichten aan de hand van een fictieve onderneming met aan het hoofd een CEO (Chief Executive Officer) en diverse werknemers die de bevelen uitvoeren van de CEO. Het bedrijf heeft (gelukkig) ook een Partner die de zaken nog kan bijsturen als de CEO weer eens zijn zoveelste impulsieve gedachtenkronkel heeft en dingen heeft opgestart die bij voorbaat al kansloos zijn.
De CEO kan gezien worden als een hoofdcomponent met een partner-subcomponent en een werknemer-subcomponent. In de schermafbeelding hieronder komt dat tot uiting in een rood blok zijnde hoofdcomponent Ceo.razor. De subcomponenten zijn geïntegreerd in de hoofdcomponent en dat komt tot uiting in respectievelijk het grijze blok voor subcomponent Werknemer.razor en het groene blok voor subcomponent Partner.razor:
We bekijken ons project met de Visual Studio Solution Explorer en we vinden hoofdcomponent Ceo.razor terug in folder Pages en de subcomponenten Werknemer.razor en Partner.razor in folder SubComponents:
Hoofdcomponent
Component Ceo.razor staat voor de CEO waarbij voor zijn ondergeschikten twee subcomponenten aanwezig zijn (Werknemer.razor en Partner.razor). In Ceo.razor vind je verwijzingen naar de subcomponenten (regel 24 t/m 28) waarbij de waarden van de public variabelen Land en Product (regel 12 en 14) worden meegegeven als zijnde bevelen naar de ondergeschikten.
Subcomponent Partner.razor kan de waarden van de public variabelen in Ceo.razor veranderen omdat de partner een two-way binding heeft. Subcomponent Werknemer.razor kan de waarden van de public variabelen daarentegen niet veranderen omdat de werknemer een one-way binding heeft.
Binnen Ceo.razor wordt alles vanuit de tekstboxen eerst in private variabelen gezet (verzonnen_land en verzonnen_product) en de public variabelen (Land en Product) krijgen na de muisklik de waarden toegekend van de private variabelen. De waarden van de public variabelen worden vervolgens doorgegeven aan de subcomponenten (het besluit van de CEO wordt uitgerold binnen de organisatie).
One-way binding
De CEO is met het lumineuze idee gekomen om zonnebanken te verkopen in Ethiopië. Het idee slaat nergens op en iedereen beseft dat op de CEO na. De mensen in de hoorn van Afrika hebben wel andere dingen aan hun hoofd en de aanschaf van een zonnebank is waarschijnlijk het allerlaatste waar ze aan denken.
We hebben desalniettemin een One-way binding bevelstructuur, het wordt opgelegd van bovenaf en de medewerkers hebben niks in te brengen. Vanuit hoofdcomponent Ceo.razor wordt als volgt een link gelegd naar subcomponent Werknemer.razor:
<BlazorBlogProject.Client.SubComponents.Werknemer
Land=@Land Product=@Product />
In subcomponent Werknemer.razor hebben we een Land-property en een Product-property en de hoofdcomponent levert de waarden aan voor de properties van de subcomponent. De waarden komen binnen bij de subcomponent als een inkomende parameter en we zien dat daarvoor de [Parameter]-attribuut binnen subcomponent Werknemer.razor wordt gebruikt:
De waarden worden aangeleverd door de CEO (Ceo.razor) of indirect via de Partner (Partner.razor) en de inkomende waarden worden netjes neergezet in een paragraph (<p>). De medewerker stelt verder geen vragen want wat binnenkomt, dat is door de one-way binding een gegeven waar niks aan gewijzigd kan worden.
Two-way binding
Gelukkig heeft de onderneming een partner die invloed heeft op de CEO en die de dingen nog kan bijsturen. Er kunnen wat kanttekeningen geplaatst worden bij producten die zorgen voor een getinte huidskleur i.v.m. mogelijke huidaandoeningen, maar de partner wil niet geheel tegen de haren van de CEO instrijken en besluit het idee wat af te zwakken.
Gezichtsbruiners gaan verkocht worden in plaats van zonnebanken en de aandacht wordt verlegd naar Svalbard (Spitsbergen – Noorwegen). Svalbard is mogelijk een beter afzetgebied. De inwoners van Svalbard leven van november tot eind februari in volledige duisternis en misschien dat men oren heeft naar een gezichtsbruiner gezien de volledige afwezigheid van zonlicht in die periode. Vanuit hoofdcomponent Ceo.razor wordt als volgt een link gelegd naar subcomponent Partner.razor:
<BlazorBlogProject.Client.SubComponents.Partner
@bind-Land=Land @bind-Product=Product />
Het is geen éénrichtingsverkeer meer. De CEO heeft weliswaar geen luisterend oor voor de allerlaagste levensvormen (werknemers), maar hij staat wel open voor de suggesties van zijn partner en de te gebruiken attributen zijn daardoor ook anders. Voor het doorgeven van de waarden naar subcomponent Partner.razor wordt een @bind-prefix gebruikt waarmee wordt aangegeven dat er een two-way binding is.
De corrigerende acties van de partner komen als volgt tot uiting in subcomponent Partner.razor:
Voor de inkomende parameters moeten bijbehorende call back events / EventCallback(s) gedefinieerd worden (regel 18 en 24) die een terugkoppeling mogelijk maken naar de hoofdcomponent (Ceo.razor).
Met de await LandChanged.InvokeAsync(Land) en de ProductChanged.InvokeAsync(Product) (regel 30-31) geef je aan wat teruggekoppeld moet worden naar de hoofdcomponent en in dit geval gaat het om de publieke variabelen Land en Product van Ceo.razor.
Binnen Partner.razor wordt alles vanuit de tekstboxen eerst in private variabelen gezet (gecorrigeerd_land en gecorrigeerd_product) en de public variabelen (Land en Product) krijgen na de muisklik de waarden toegekend van de private variabelen. De waarden van de public variabelen worden vervolgens teruggegeven aan hoofdcomponent CEO en via de hoofdcomponent komen de waarden terecht bij subcomponent Werknemer.
De partner heeft een bijsturing gedaan want de aandacht wordt verlegd naar Svalbard en men probeert eerst de gezichtsbruiners te slijten zodat het financiële leed wat minder is als de mensen van Svalbard niet geïnteresseerd mochten zijn in gezichtsbruiners. De desbetreffende publieke variabelen van Ceo.razor zullen dan ook een andere waarde krijgen na de bijsturing door Partner.razor.
Slot
In deze post hebben we de interactie / binding laten zien tussen een hoofdcomponent en subcomponenten. We hebben het geïllustreerd met het voorbeeld van een fictieve onderneming met aan het hoofd een CEO en daaronder een partner en wat werknemers.
Voor de CEO hebben we een hoofdcomponent aangemaakt met verwijzingen naar subcomponenten. Voor subcomponent werknemer is een one-way binding van toepassing met één-richtingsverkeer van de hoofdcomponent (CEO) naar de subcomponent (werknemer). Voor subcomponent partner is een two-way binding van toepassing en we zien dat de partner daardoor de waarden van de public variabelen van de hoofdcomponent kan wijzigen.
Hopelijk ben je met deze posting weer wat wijzer geworden en ik hoop je weer terug te zien in één van mijn volgende blog posts. Wil je weten wat ik nog meer over Blazor heb geschreven? Hit the Blazor button…