2013-02-26 2 views
5

Я довольно новичок в Дюрандале. У меня небольшой опыт работы с KnockoutJS. Я пытаюсь заполнить наблюдаемый массив из json, полученный из файла php. Затем я пытаюсь загрузить массив в таблицу. Кажется, что возникает проблема при загрузке данных в таблицу при первой загрузке страницы. Я выполняю system.log (клиентов), чтобы убедиться, что данные находятся в наблюдаемом массиве, который он есть. Когда я обновляю страницу, данные загружаются в таблицу, как я хочу. Похоже, что наблюдаемый массив заполняется, но представление не обновляется.Как использовать наблюдаемые в Дюрандале?

Мне было интересно, что я делаю неправильно, чтобы он не загружался при первой загрузке страницы. Вот тестовый сайт, на котором я играл с durandal: http://dev.codeplanetapps.com/spa/. После загрузки нажмите «Клиенты». Эта страница - http://dev.codeplanetapps.com/spa/#/customers. Когда эта страница загружается напрямую, она работает нормально, но когда я загружаю приложение с главной страницы и затем переключаюсь на клиентов, он не загружает таблицу правильно. Заранее благодарю за любую помощь.

Вот вид:

<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> 

А вот 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); 
     } 
    }; 
}); 

Кроме того, в качестве побочного сведению, что Jquery в верхней и нижней части Activate функция работает только в том случае, если я окружаю их в функции setTimeout(). Я привел пример datepicker. Это не так важно, но если кто-нибудь знает, как это исправить, я бы очень признателен.

ответ

9

Спасибо, Пол. Я опаздывал прошлой ночью. Я забыл ответить, чтобы добавить ответ. Я получил ответ от Роба Эйзенберга, создателя Дюрандаля. Моя ошибка заключалась в том, что мне нужно было вернуть обещание от вызова .getJSON(). Мне также нужно было добавить еще одну функцию, viewAttached(), в модуль для всех моих вызовов jQuery, которые относятся к элементу в DOM.

Вот ответ Роба на Help with observableArray not updating in view. Они действительно полезны в этой группе. Роб довольно быстро отвечает на большинство вопросов.

Ниже приведен исправленный код для 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

спасибо, smalone. Это решение, которое я искал. – Blaise

+1

Вы очень желанны. Я много узнал о Дюрандале за несколько недель, с которыми я работал. Это было спасателем жизни для разработки приложений с одной страницей. – smalone

+0

Awesome. спасибо за размещение решения – ajeeshpu

0

Я не знаю, изменили ли вы что-либо после публикации вопроса, но оно работает для меня в IE 9, Opera 12 и Chrome. Ошибка в IE 9, lines 45 and 46 из shell.js, event.currentTarget.classList иногда равна null, поэтому вы должны это проверить, но если я перейду к вашему приложению и нажимаю на Клиенты, в таблице будут данные.

+0

Я понял мою проблему. Я разместил его как решение выше. Спасибо за проверку. – smalone

Смежные вопросы