5

私はデュランダルにかなり慣れていません。KnockoutJSの使用経験は少しあります。phpファイルから取得したjsonからobservableArrayにデータを入力しようとしています。次に、配列をテーブルにロードしようとしています。ページの最初のロード時にデータをテーブルにロードするときに問題があるようです。system.log(customers)を実行して、データがobservableArrayにあることを確認します。ページを更新すると、データが希望どおりにテーブルに読み込まれます。observableArrayにデータが入力されているように見えますが、ビューは更新されていません。

ページの最初のロードでロードされないために、何が間違っているのか疑問に思いました。これが私が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>

そしてここにビューモデルがあります:

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);
        }
    };
});

また、補足として、activate関数の上部と下部にあるjQueryは、それらをsetTimeout()関数で囲んだ場合にのみ機能します。例として、日付ピッカーを残しました。それはそれほど重要ではありませんが、誰かがそれを修正する方法を知っているなら、私はそれを大いに感謝します。

4

2 に答える 2

9

ありがとう、ポール。私は昨夜遅くまで起きていました。答えを追加するために返信するのを忘れました。デュランダルの作者であるロブ・アイゼンバーグから回答がありました。私の間違いは、.getJSON()呼び出しからpromiseを返す必要があるということでした。また、DOM内の要素を参照するすべてのjQuery呼び出しのモジュールに、別の関数viewAttached()を追加する必要がありました。

これは、ビューでobservableArrayが更新されないヘルプに対するRobの返信です。彼らはこのグループで本当に役に立ちます。ロブはほとんどの質問にすぐに答えます。

以下は、ビューモデルの修正されたコードです。

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
于 2013-02-26T16:13:05.750 に答える
0

質問を投稿してから何か変更したかどうかはわかりませんが、IE 9、Opera 12、Chromeでは機能します。IE 9でスローされるエラーがありlines 45 and 46shell.jsevent.currentTarget.classListnullになることがあるので、それを確認する必要がありますが、アプリに移動して[顧客]をクリックすると、テーブルにデータがあります。

于 2013-02-26T09:17:07.127 に答える