QUIZ - aplikacja ASP.NET MVC z Knockout

Autorzy: Grzegorz Janik


C#, ASP.NET, AJAX, JavaScript, MVC, Knockout


Artykuł ten jest trzecią częścią serii, która ukazywać się będzie na stronie koła informatycznego Reset. Artykuły przedstawiać będą rozwiązanie problemu dotyczącego napisania prostego quizu internetowego „Co to za gra?”. W tym przypadku zastosowaną technologią do rozwiązania problemu będzie ASP.NET MVC z wykorzystaniem Ajax oraz Knockout.
Artykuł został napisany w ramach staży realizowanych w firmie LGBS Polska.

Wstęp

Nawiązując do poprzedniego artykułu, w którym tworzyliśmy Quiz w czystym ASP.NET MVC, spróbujemy przekształcić ten projekt tak, aby wykorzystać wspomniane technologie, tj. jQuery Ajax[http://api.jquery.com/category/ajax/] oraz Knockout [http://knockoutjs.com/].

Będziemy bazować na projekcie wykonanym w I części serii [QUIZ-Aplikacja w ASP.NET MVC cz.I].

Knockout jest rozbudowanym JavaScriptowym frameworkiem MVVM. Umożliwia on odwzorowanie naszego modelu po stronie klienta w postaci JSON oraz zbindowanie go z fragmentami strony wyświetlanej użytkownikowi. Oznacza to, że każda zmiana zbindowanego pola w widoku spowoduje zaktualizowanie pola naszego modelu i vice versa.

Aby przystąpić do wykonania zadania z wykorzystaniem AJAX i Knockout należy przygotować dane w formacie JSON, o które będzie odpytywany serwer, a które będą wykorzystane do wygenerowania treści quizu oraz akcję kontrolera odpowiedzialną za sprawdzanie odpowiedzi i wysyłanie nowego pytania. W tym artykule wykorzystamy istniejące już metody i dane, które są opisane w artykułach autorstwa Piotra Romańskiego [QUIZ-Aplikacja ASP.NET MVC cz.I , QUIZ - aplikacja ASP.NET MVC z jQuery Template ]. Będą to:

 

- public JsonResult GetQuestion()
- public JsonResult CheckAnswer(int answerId)

 

 

oraz cały serwis do obsługi repozytorium z grami także napisany przez wspomnianego wyżej autora.

 

Potrzebne biblioteki

Do wykonania zadania będzie nam potrzebne nic innego jak Knockout - http://knockoutjs.com/downloads/knockout-3.1.0.js oraz skrypt do mapowania danych w formacie JSON do naszego View Modelu - https://github.com/SteveSanderson/knockout.mapping/tree/master/build/output

Skrypty te są dostępne na stronie twórców, aczkolwiek można je także pobrać przez managera pakietów NuGet, co uczyniono w tym przypadku.

Knockout w akcji

Po zainstalowaniu pakietów widok folderu z naszymi skryptami powinien wyglądać następująco:

zrzut_1

 

Następnie skrypty- w zależności od uznania programisty -należy dodać do Bundle MVC bądź pliku widoku, w którym będziemy je wykorzystywać.

Stwórzmy teraz nowy plik KnockoutQuiz.js ,w którym napiszemy nasz skrypt wykorzystujący Knockout. Dodajmy go do kodu HTML tak, jak powyższe skrypty.

Przejdźmy do sedna  artykułu, czyli kodu skryptu, który wykorzysta wszystkie możliwości  dostarczane przez Knockouta:

 

var viewModel = {    
    SelectedAnswer: ko.observable(),
    Question: {    
        Answers: ko.observableArray(),
        ImagePath: ko.observable(),
        Result: ko.observable(),
        IsCorrect: ko.observable(),
    },
    CheckAnswer: function () {
        if (!viewModel.SelectedAnswer()) {
            alert("Proszę wybrać odpowiedź");
            return;
        }
        $.ajax({
            url: '/Knockout/CheckAnswer,
            data: {
                answerId: viewModel.SelectedAnswer
            },
            success: function (data) {
                ko.mapping.fromJS(data, viewModel.Question);
                viewModel.SelectedAnswer(false);
            }
        });
    }
};
$.getJSON("/Knockout/GetQuestion", function (data) {
    $(function () {
        viewModel.Question = ko.mapping.fromJS(data);
        ko.applyBindings(viewModel);
    });
});

Fragment strony HTML, ze zbindowanymi polami napisanego przez nas View Modelu:

 

    <div id="quiz">
        <h3 data-bind="if: Question.IsCorrect()">Brawo! Udzielono poprawnej odpowiedzi!</h3>
    	 <div data-bind="if: (!Question.IsCorrect() && Question.Result()!=null)">
        	<h3>Źle, poprawna odpowiedź to: </h3>
        	<h2 data-bind="text: Question.Result"></h2>
    	 </div>
        <img data-bind="attr:{src: Question.ImagePath}" width="500" height="280" />
        <div data-bind="foreach: Question.Answers">
            <label>
                <input name="radioButtons"
                       type="radio"
                       data-bind="value: $data.AnswerId, checked: $parent.SelectedAnswer" />
                <span data-bind="text: $data.Name"></span>
            </label><br />
        </div>
        <button data-bind="click: CheckAnswer"> Następne pytanie </button>
    </div>

 

W skrypcie definiujemy viewModel, który będzie zawierał 3 pola - z czego jedno będzie funkcją do pobrania nowego pytania i przesłania odpowiedzi. Pole Question zawiera w sobie cztery kolejne pola, które odwzorowują dostarczone nam przez serwer pytania. SelectedAnswer jest polem, które będzie przetrzymywać wybraną przez użytkownika odpowiedź. Z kolei CheckAnswer jest funkcją, która wyśle do serwera  wybraną przez użytkownika odpowiedź i pobierze nowe pytanie.

Po wejściu na stronę, gdzie znajdować się będzie quiz, zostanie wywołana funkcja $.getJSON. Zwrócone przez serwer dane w formacie JSON (data) zostaną zmapowane do pola Question w viewModel, a następnie zostanie on zbindowany (ko.applyBindings). Co oznacza zbindowanie? Wszędzie tam gdzie w HTML'u użyliśmy atrybutu data-bind="NazwaAtrybutu: PoleViewModelu" zostaną odpowiednio przypisane wartości View Modelu, a zawierające je pola zostaną skojarzone. Bindowanie sugerowanych pytań odbywa się za pomocą data-bind="foreach: Question.Answers" po to, aby dla każdego pytania wygenerować radiobutton z nazwą gry.  $data - jest niczym innym jak wartością elementu tablicy, a $parent - odwołuje się do elementu nadrzędnego, czyli w naszym wypadku viewModel. Do przycisku "Sprawdź" zbindowaliśmy pole CheckAnswer. Po jego wciśnięciu zostanie sprawdzone czy jakakolwiek odpowiedź została zaznaczona przez użytkownika- jeżeli tak. to do serwera zostanie wysłane zapytanie. W przeciwnym wypadku zostanie zwrócony komunikat alert("Proszę wybrać odpowiedź").  W momencie, gdy wszystko się powiedzie nasze pole Question w viewModel zostanie zaktualizowane nowymi danymi, a skojarzone pola HTML zostaną uaktualnione. Pole SelectedAnswer zostanie ustawione na false. Jest to wymagane, ponieważ w przypadku, gdy pobierzemy nowe pytanie, a w ich puli odpowiedzi będzie zaznaczona wcześniej odpowiedź to pozostałaby ona wciąż zaznaczona- jest to błąd, ponieważ zaznaczenie powinno być puste.

W widoku bindując adekwatny komunikat do udzielonej wcześniej odpowiedzi użyliśmy właściwości if atrybutu data-bind, która jest niczym innym jak odwzorowaniem dobrze nam znanego wyrażenia warunkowego. Należy tutaj wspomnieć, że aby pobrać wartość pola View Modelu trzeba się do niego odwołać jak do funkcji z "()". Dzieje się tak dlatego, gdyż pola, które udostępnia Knockout są typu funkcyjnego.

Efekt końcowy:

zrzut_2

Gotowy projekt z kodem I i II części serii quizu "Co to za gra?"

Do pobrania

 

Technologie przedstawione w niniejszym artykule pozwoliły na wstępne poznanie jQuery Ajax oraz Knockout. Autor zachęca do szerszego zapoznania się z zaprezentowanymi technologiami.

 

Liczba ocen: 9 | Średnia ocen: 4.56

Czytaj także

 

Skomentuj

Twój komentarz
Dodaj

Komentarze

Nasz Fanpage

Popularne treści

  • .NET  
  • 3D  
  • 8  
  • ActiveDirectory  
  • AJAX  
  • amazon web services  
  • Android  
  • Android Market  
  • AngularJS  
  • Animacja  
  • API  
  • aplikacje  
  • Aplikacje wielojęzyczne  
  • asembler  
  • ASHX  
  • ASP.NET  
  • ASP.NET MVC  
  • assembler  
  • Automated Installation Kit  
  • Azure  
  • bezpieczeństwo  
  • bing  
  • Blender  
  • C#  
  • certyfikat  
  • chmura  
  • cloud computing  
  • cmd  
  • Cmdlet  
  • Cmdlet’ów  
  • core  
  • CSS  
  • Cycles  
  • developer  
  • Entity Framework  
  • Expression Blend  
  • fitl  
  • google  
  • google app engine  
  • googlemaps  
  • GPU  
  • Grafika  
  • GroupPolicy  
  • hamachi  
  • hyperv  
  • hyper-v  
  • IaaS  
  • ImageX  
  • instalacja aplikacji  
  • interface  
  • interfejs  
  • Iron Speed  
  • java  
  • JavaScript  
  • jQuery  
  • Kinect  
  • Knockout  
  • kolokacja  
  • konsola  
  • LINQ  
  • LINQ to SQL  
  • Linux  
  • MakeCert  
  • maps  
  • microsoft  
  • mobile  
  • moduły  
  • MVC  
  • mySQL  
  • OpenSource  
  • openstreet  
  • openvpn  
  • PaaS  
  • partycja  
  • PHP  
  • pliki apk  
  • pon  
  • powershell  
  • preview  
  • programowanie  
  • przeglądarka  
  • przetwarzanie w chmurze  
  • przewodnik  
  • Qt  
  • RAD  
  • Rendering  
  • SaaS  
  • script  
  • SDK  
  • server  
  • serwer  
  • Skalowanie  
  • SQL  
  • Systemy operacyjne  
  • światłowody  
  • Światłowód  
  • Template  
  • ubuntu  
  • virtual  
  • Visual Studio  
  • vpn  
  • WAIK  
  • WCF  
  • WebAdministration  
  • WebApi  
  • Windows  
  • windows azure  
  • Windows PE  
  • Windows Phone  
  • WinFroms  
  • wirtualizacja  
  • WPF  
  • XAML  
  • zdalny  
  • zdjęcia  
Komu polecasz tą stronę? (email)
Poleca (twoje imie/pseudonim)
Treść (opcjonalnie) Do Twojej treści zostanie dodany link polecanej strony
POLECAM