Binding to mechanizm wiążący dane z interfejsem użytkownika. Jak nie zbindujemy danych z kontrolką to chociaż po stronie serwera wszystko działa jak należy to po stronie klienta … leży. Napisałem po stronie serwera, ale w Aurelii wszystko dzieje się po stronie klienta, a więc to nie tak, że po stronie serwera, a raczej model widoku musi być powiązana z widokiem, a idąc w głąb elementy modelu muszą być powiązane z elementami interfejsu użytkownika.
Sposobów na bindowanie jest kilka:
- String interpolation
export class App { upperVersion = 'Test'; } <template> <div> <input value="${upperVersion}"> </div> </template>
I już. Po załadowaniu strony nasz input zostanie wypełniony wartością „Test”. Należy pamiętać, że w tym przypadku zmiany np:. w textbox’sie nie będą widoczne po stronie ViewModelu.
- bind, czyli co jeżeli interpolacja stringów nam się nie podoba albo chcielibyśmy mieć aktualne dane w ViewModelu.
<template> <div> <input value.bind="upperVersion"> </div> </template> export class App { upperVersion = 'Test'; }
Zamiast używania interpolacji wystarczy dodać .bind do atrybutu value i użyć nazwy zmiennej klasy. O rodzajach bindowania napiszę w innym poście.
- Value converter pipe „|” – jeżeli chcemy, aby wartość przesłana z widoku była wyświetlona w oczekiwanej przez użytkownika postaci należy tą wartość odpowiednio skonwertować. Idealnym rozwiązaniem w Aurelii jest użycie konwerterów wartości (value converter).
export class App { upperVersion = ''; } export class ToUpperValueConverter { toView(value) { return value.toUpperCase(); } } <template> <div> <input value="${upperVersion | toUpper}"> </div> </template>
W stosunku do przykładu z punktu 1, dodałem tylko prostą klasę konwertera wykorzystującą funkcję toUpperCase() z biblioteki jQuery oraz modyfikację bindingu inputa.
- Zachowania to kolejny sposób służący do sterowania bindingiem i podobnie do konwerterów wartości możemy wstawiać je do potoku w interpolowanym stringu, ale zamiast „|” użyjemy „&”:
Wyróżniamy następujące zachowania: throttle, debounce, updateTrigger, signal i oneTime. Więcej o zachowaniach bindingu napiszę w kolejnym poście, a tymczasem przedstawię ideę działania na jednym z nich – signal, które wysyła sygnał o potrzebie odświeżenia wartości w kontrolce. Poniższy przykład – chociaż nie najwyższych lotów – powoduje wyświetlenie aktualnej sekundy, po wciśnięciu buttona, który wysyła sygnał. Można oczywiście to zrobić na samym onclicku buttona bez wysyłania sygnału, ale wtedy nie byłoby prezentacji tego jak działa zachowanie.<template> <require from="bootstrap/css/bootstrap.css"></require> <div class="container"> <div> <label>${null| toSeconds & oneTime & signal: 'test-signal' }</label> <button click.trigger="testSignal()">Send signal</button> </div> </template> import {inject} from 'aurelia-framework'; import {BindingSignaler} from 'aurelia-templating-resources'; @inject(BindingSignaler)export class App { constructor(signaler) { this.signaler = signaler; } testSignal() { this.signaler.signal('test-signal'); } } export class ToSecondsValueConverter { toView() { return new Date().getSeconds(); } }
- @observable – użycie tego dekoratora pozwala rozpoznawać zmiany wartości zmiennej, a do tego można połączyć to z fajnym, automagicznym mechanizmem Aurelii, który po zmianie wartości zmiennej wywołuje na niej funkcję [nazwa_zmiennej]Changed, jeżeli taka funkcja istnieje. W moim przykładzie jest to testChanged. Nigdzie nie jest jawnie wywoływana, a jednak robi to co trzeba.
<template> <input type="text" value.bind="test"> <label>${repeatText}</label> </template> import {observable} from 'aurelia-framework'; export class App { @observable test = ''; repeatText = ''; testChanged(newVal){ this.repeatText = newVal; } }