2013-07-04 4 views
6

Po prostu zaglądam do knockout.js z MVC-Web-API i próbuję stworzyć stronę Hello World, która aktualizuje czas na stronie co 5 sekund . Wykonuje połączenie co 5 sekund, widzę to w moim kontrolerze (punkcie przerwania), ale wciąż nic nie wyświetla się na ekranie.Knockout.js - Strona aktualizacji co 5 sekund z nową wartością

AKTUALIZACJA: Nadal pracuję nad tym i teraz ustaliłem, że otrzymuję dane z powrotem z serwera, wywołanie jest wysyłane do kontrolera co 5 sekund, a to zwraca JSON I potrzeby (wyświetlają się ostrzeżenia), ale na elemencie przęsła na stronie wciąż nie wyświetla się nic.

Muszę realistycznie użyć funkcji mapowania, ponieważ tworzę większą witrynę internetową, która ma model z ponad 50 właściwościami i nie chce specjalnie przeglądać ich pojedynczo w viewmodelu.

Podałem mój kod poniżej.

<span data-bind="text: TimeString"></span> 

<script type="text/javascript"> 
    var viewModel; 
var getUpdates = setInterval(function() { 
    $.getJSON(
     "/Values/Get", {}, 
     function (model) { 
      alert(model.TimeString); 
      ko.mapping.fromJS(model, viewModel); 
     }); 
}, 5000); 

$(document).ready(
    function() { 
     $.getJSON(
      "/Values/Get", {}, 
      function (model) { 
       var viewModel = ko.mapping.fromJS(model); 
       alert(model.TimeString); 
       ko.applyBindings(viewModel); 
      }); 
    }); 

function bindViewModel(model) { 
    ko.applyBindings(model); 
} 

public class HelloWorldModel 
{ 
    public DateTime TimeDT { get; set; } 
    public String TimeString { get; set; } 
} 

    public class ValuesController : Controller 
{ 
    public HelloWorldModel Model = new HelloWorldModel(); 

    [System.Web.Mvc.AcceptVerbs(HttpVerbs.Get)] 
    public JsonResult Get() 
    { 
     Model.TimeDT = DateTime.Now; 
     Model.TimeString = Model.TimeDT.ToString("HH:mm:ss"); 

     return Json(Model, JsonRequestBehavior.AllowGet); 
    } 

    // POST api/values 
    public void Post([FromBody]string value) 
    { 
    } 

    // PUT api/values/5 
    public void Put(int id, [FromBody]string value) 
    { 
    } 

    // DELETE api/values/5 
    public void Delete(int id) 
    { 
    } 
} 
} 
+0

Co to jest "dane" w powiązaniu? Czy to jest niestandardowe powiązanie? Lub masz na myśli ''? – nemesv

+0

Skąd się bierze aktualizacjaFromJSON? W dokumentacji jest napisane: ko.mapping.fromJS (data, viewModel); – Peter

+0

Powinieneś używać wtyczki do mapowania w swoim oryginalnym wywołaniu AJAX, a nie tylko tym, który powtarza się co 5 sekund. –

Odpowiedz

6

Jeśli zastosujemy documentation, to nie powinno być zbyt trudne. W swojej pierwszej rozmowy do serwera, wykonaj następujące czynności:

var viewModel = ko.mapping.fromJS(model); 
ko.applyBindings(viewModel); 

Aplikujesz powiązania z obiektem JS (getJSON zwraca obiekt JS, a nie ciąg JSON, jeśli mam poprawnie czyta the documentation).

Po tym, w powtarzających się funkcji, wykonaj następujące czynności:

ko.mapping.fromJS(model, viewModel); 

Z dokumentacji:

  • Wszystkie właściwości obiektu są przekształcane w zauważalny. Jeśli aktualizacja spowodowałaby zmianę wartości, zaktualizuje to obserwowalne.
  • Tablice są konwertowane na możliwe do zaobserwowania tablice. Jeśli aktualizacja spowodowałaby zmianę liczby elementów, wykona odpowiednie akcje add/remove . Spróbuje również zachować kolejność tak samo, jak oryginalna tablica JavaScript w wersji .
4

Nie trzeba wymienić kompletny widok model i może zamiast aktualizować właściwości zwrócony z żądania Ajax, tak:

$(function() { 
    var vm = { 
     TimeDT: ko.observable(), 
     TimeString: ko.observable() 
    }; 

    function updateValues() {  
     $.getJSON("/Values/Get").done(function(data) { 
      vm.TimeDT(data.TimeDT); 
      vm.TimeString(data.TimeString); 
     }); 
    } 

    ko.applyBindings(vm); 

    updateValues(); 
    setInterval(updateValues, 5000); 
}); 

Widać tu small example zrobiłem w JsFiddle.

+0

To prawda, że ​​nie musi całkowicie zastępować modelu widoku. Ale dzięki temu rozwiązaniu znowu wykonujesz całą pracę. Zaletą wtyczki do mapowania KO jest to, że robi to za Ciebie. Za pierwszym razem (podczas tworzenia viewmodel), ale także później, kiedy chcesz zaktualizować swój viewmodel. Uaktualni on wszystkie obserwowalne dla ciebie (z 'ko.mapping.fromJS (model, viewModel);). Jest to interesujące, gdy masz kilka obserwowalnych właściwości i kiedy dodajesz właściwości w czasie. – Peter

+0

Tak, zgadzam się z tobą również. W takim przypadku jego bieżący ViewModel byłby własnością bardziej złożonego (skomponowanego?) Modelu ViewModel. Opublikowana przeze mnie odpowiedź jest skuteczna w prostych scenariuszach, takich jak ten, który Ben umieścił w swoim przykładzie. – Meryovi

3

Nota prawna: Współpracuję z Benem.

Jest kilka problemów z kodem, po pierwsze brakuje niektórych odwołań do javascriptu, po drugie obiekt viewModel zawsze ma wartość zerową za każdym razem, gdy upływa czas.

Należy pobrać plik mapowania nokautów w formacie Javascript z here, nazwać go knockout.mapping-latest.js i zapisać w katalogu Scripts. Następnie upewnij się, że dodano odwołania do jquery i knockout.js.

Uaktualniona widok Razor jest poniżej:

<div id="body"> 

    <span data-bind='text: TimeString'></span> 

    <script src="~/Scripts/jquery-1.8.2.js" type="text/javascript"></script> 
    <script src="~/Scripts/knockout-2.2.0.debug.js" type="text/javascript"></script> 
    <script src="~/Scripts/knockout.mapping-latest.js" type="text/javascript"></script> 
    <script type="text/javascript"> 
     var viewModel; 
     var getUpdates = setInterval(function() { 
      $.getJSON(
       "/Values/Get", {}, 
       function (model) { 
        //alert(model.TimeString); 
        ko.mapping.fromJS(model, viewModel); 
       }); 
     }, 5000); 

     var viewModelSet = false; 

     $(document).ready(
      function() { 
       $.getJSON(
        "/Values/Get", {}, 
        function (model) { 
         viewModel = ko.mapping.fromJS(model); 
         ko.applyBindings(viewModel); 
        }); 
      }); 

     function bindViewModel(model) { 
      ko.applyBindings(model); 
     } 
    </script>  

</div> 

Wystarczy dodać, pól publicznych w klasie są generalnie nie-go, w Twój ViewModel instancja HelloWorldModel nie uzyskać dostęp z dowolnego innego w kod, tylko z poziomu tej klasy, więc może być prywatny. Jeśli uzyskano do niego dostęp z innych źródeł, najlepszą praktyką byłoby zachowanie prywatności i udostępnienie go za pośrednictwem nieruchomości. Więcej informacji: here.