2013-02-26 12 views
5

Jestem całkiem nowy w Durandal. Mam małe doświadczenie z KnockoutJS. Próbuję wypełnić observableArray z json pobrany z pliku php. Próbuję następnie załadować tablicę do tabeli. Wydaje się, że występuje problem podczas ładowania danych do tabeli po pierwszym załadowaniu strony. Wykonuję system.log (klienci) tylko po to, aby upewnić się, że dane znajdują się w obserwowalnej tablicy, którą jest. Po odświeżeniu strony dane są ładowane do tabeli tak, jak chcę. Wygląda na to, że obiekt obserwowalny jest zapełniany, ale widok nie jest aktualizowany.Jak korzystać z obserwowalnych w Durandal?

Zastanawiam się, co robię źle, aby nie ładować się przy pierwszym załadowaniu strony. Oto strona testowa, w którą grałem z durandal: http://dev.codeplanetapps.com/spa/. Po załadowaniu kliknij "Klienci". Dana strona to http://dev.codeplanetapps.com/spa/#/customers. Kiedy ta strona jest ładowana bezpośrednio, działa dobrze, ale kiedy ładuję aplikację ze strony głównej, a następnie przełączam się na klientów, to nie ładuje ona poprawnie tabeli. Z góry dziękuję za pomoc.

Oto widok:

<div> 
<!-- Form to add new customer --> 
<form class="form-inline customerForm"> 
    <span>Add New Customer</span> 
    <input type="text" data-bind="value: inputName" placeholder="Name" /> 
    <input type="text" class="date input-small" data-bind="value: inputDOB" placeholder="Date of Birth" /> 
    <input type="text" class="input-small" data-bind="value: inputPhone" placeholder="Phone" /> 
    <input type="text" data-bind="value: inputEmail" placeholder="Email" /> 
    <button type="submit" class="btn btn-primary" data-bind="click: submitCustomer">Add</button> 
</form> 

<table class="table table-hover table-bordered customerTable"> 
    <thead> 
     <tr> 
      <th>Name</th> 
      <th>DOB</th> 
      <th>Phone Number</th> 
      <th>Email</th> 
      <th></th> 
     </tr> 
    </thead> 
    <tbody data-bind="foreach: customers"> 
     <tr> 
      <td data-bind="text: name"></td> 
      <td data-bind="text: dob"></td> 
      <td data-bind="text: phone"></td> 
      <td data-bind="text: email"></td> 
      <td><button class="btn btn-danger btn-mini" data-bind="click: $root.removeCustomer">Delete</button></td> 
     </tr> 
    </tbody> 
</table> 

A oto ViewModel:

define(function(require){ 
    // Load System for debugging 
    var system = require('durandal/system'); 

    // Customer Structure 
    function Customer(data) { 
     this.name = ko.observable(data.name); 
     this.dob = ko.observable(data.dob.substring(5,7) + '/' 
      + data.dob.substring(8,10) + '/' + data.dob.substring(0,4)); 
     this.phone = ko.observable(data.phone); 
     this.email = ko.observable(data.email); 
    }; 

    // Form observables 
    var inputName = ko.observable(''); 
    var inputDOB = ko.observable(''); 
    var inputPhone = ko.observable(''); 
    var inputEmail = ko.observable(''); 
    // Customers array 
    var customers = ko.observableArray([]); 

    return { 
     inputName: inputName, 
     inputDOB: inputDOB, 
     inputPhone: inputPhone, 
     inputEmail: inputEmail, 
     customers: customers, 
     // This performs any needed functionality after the page loads 
     activate: function(data) { 
      // Change the selected nav item 
      $('.customerNav').addClass('active'); 
      $('.firstNav').removeClass('active'); 
      $('.secondNav').removeClass('active'); 

      // Get current customers from database and add to customers observableArray 
      $.getJSON(
       // Backend script 
       'php/query.php', 
       // Variables sent to query.php 
       { 
        mode: 'select', 
        table: 'customers', 
        'fields[]': '*', 
        'values[]': '*' 
       }, 
       // Callback function 
       function(data) { 
        var customer = $.map(data, function(item) {return new Customer(item) }); 
        customers(customer); 
       } 
      ); 

      // For some reason I couldn't get the datepicker to work without make the page 
      // wait 50 milliseconds. 
      setTimeout(function() { 
      $('.date').datepicker(); 
      },500); 
     } 
    }; 
}); 

Również jako marginesie, jQuery na górze i na dole activate Funkcja działa tylko wtedy, gdy otacza ich funkcja setTimeout(). Zostawiłem datepicker jako przykład. To nie jest tak ważne, ale jeśli ktoś wie, jak to naprawić, byłbym bardzo wdzięczny.

Odpowiedz

9

Dzięki, Paul. Wczoraj wieczorem spałem późno. Zapomniałem odpowiedzieć, aby dodać odpowiedź. Dostałem odpowiedź od Roba Eisenberga, twórcy Durandala. Mój błąd polegał na tym, że musiałem zwrócić obietnicę z wezwania .getJSON(). Potrzebowałem również dodać kolejną funkcję, viewAttached(), do modułu dla wszystkich moich wywołań jQuery, które odnoszą się do elementu w DOM.

Oto odpowiedź Roba na Help with observableArray not updating in view. Są bardzo pomocni w tej grupie. Rob jest dość szybki, aby odpowiedzieć na większość pytań.

Poniżej znajduje się kod skorygowany viewmodel:

define(function(require){ 
// Load System for debugging 
var system = require('durandal/system'); 

// Customer Structure 
function Customer(data) { 
    this.name = ko.observable(data.name); 
    this.dob = ko.observable(data.dob.substring(5,7) + '/' 
     + data.dob.substring(8,10) + '/' + data.dob.substring(0,4)); 
    this.phone = ko.observable(data.phone); 
    this.email = ko.observable(data.email); 
}; 

// Form observables 
var inputName = ko.observable(''); 
var inputDOB = ko.observable(''); 
var inputPhone = ko.observable(''); 
var inputEmail = ko.observable(''); 
// Customers array 
var customers = ko.observableArray([]); 

return { 
    inputName: inputName, 
    inputDOB: inputDOB, 
    inputPhone: inputPhone, 
    inputEmail: inputEmail, 
    customers: customers, 
    // This allows us to add jQuery as usual 
    viewAttached: function() { 
     // Change the selected nav item 
     $('.customerNav').addClass('active'); 
     $('.firstNav').removeClass('active'); 
     $('.secondNav').removeClass('active'); 

     $('.date').datepicker(); 
    }, 
    // This performs any needed functionality after the page loads 
    activate: function(data) { 
     // Capture the module instance 
     var self = this; 

     // Get current customers from database and add to customers observableArray 
     var promise = $.getJSON(
      // Backend script 
      'php/query.php', 
      // Variables sent to query.php 
      { 
       mode: 'select', 
       table: 'customers', 
       'fields[]': '*', 
       'values[]': '*' 
      }, 
      // Callback function 
      function(data) { 
       var customer = $.map(data, function(item) {return new Customer(item) }); 
       system.log(customers); 
       self.customers(customer); 
      } 
     ); 

     return promise; 
    } 
}; 
}); // define 
+0

Dziękuję, smalone. To jest rozwiązanie, którego szukałem. – Blaise

+1

Nie ma za co. Wiele się nauczyłem o Durandalu w ciągu kilku tygodni, kiedy z nim pracowałem. Oszczędzanie życia przy tworzeniu aplikacji na jedną stronę. – smalone

+0

Awesome. dzięki za ogłoszenie rozwiązania – ajeeshpu

0

Nie wiem, czy zmieniłeś coś od czasu opublikowania pytania, ale działa to dla mnie w IE 9, Opera 12 i Chrome. Wystąpił błąd w IE 9, lines 45 and 46 z shell.js, event.currentTarget.classList jest czasami zerowy, więc powinieneś to sprawdzić, ale jeśli przejdę do Twojej aplikacji i kliknę Klientów, są dane w tabeli.

+0

zorientowali się mój problem. Wysłałem to jako rozwiązanie powyżej. Dzięki za sprawdzenie. – smalone