7

TL;DR:ノックアウトを介してバインドされた select2 フィールドに表示するためのデフォルト値を設定する必要がありますが、select2 バインディングは値を受け入れる代わりにビューモデルの値を "" にオーバーライドし続けます。

成分

私は以下を利用しています:

  • ノックアウトJS
  • 入力フィールドの Select2
  • select2 へのカスタム ノックアウト バインディング
  • ビューモデルの Start() メソッドの一部としてオブジェクト (請求書) をロードするための ajax 呼び出し。

目標

  • 初期ビューモデルのStart()関数の一部として値をロードします
  • 請求書を読み込むときに、select2 の既定値を VM の値にバインドします。
  • ユーザーが選択したときに他のオプションを選択できるようにする
    • デフォルト値は、select2 値を下げる方法により、select2 オプションにも含まれるため、必要はありません。

問題

  • 空白のフォームから開始した場合、Select2 は完全に正常に機能します。ドロップダウンなどでAjax呼び出しから値をロードします。
  • ただし、請求書を表示用にロードすると、viewmodel の値が select2 コントロールに設定されません。
    • ""select2 コントロールが実際にデータをロードし、値がまだ選択されていないため、ロード時にビューモデルの値を上書きしているように見えます..

解決しようとするこれまでの考え

私はこれらすべてを調査します:

  • ノックアウト バインディングを適切に使用して、その値の一部ではないデフォルトの要素の選択を許可していない可能性があります。
  • select2 ボックスがロードされていることを確認し、要素の更新をトリガーできる方法があれば、それも問題ありません。

コード

ドキュメントのロード

$(document).ready(function () {
    'use strict';

    console.log("creating viewmodel");
    vm = new invoiceDetailsPage.ViewModel();
    vm.Start();

    console.log("applying bindings");
    ko.applyBindings(vm);
});

請求書の詳細ページの名前空間 (一部の無関係な部分を削除)

var invoiceDetailsPage = invoiceDetailsPage || {

    InvoiceDetailItem: function () {
        'use strict';
        var self = this;


        self.DatePayable = new Date(); 
        self.Fees = 0.00;
        self.Costs = 0.00;
        self.Adjustments = ko.observable();
        self.AdjustmentNote = ko.observable();
        self.Total = ko.computed(function () {

        });

        self.hasAdjustments = ko.computed(function () {

        });

    },


    Invoice: function (invoiceID, documentTypeID, firmID, invoiceNumber, invoicePeriod, datePayable, privateComment, statusID, vendorFirmID) {
        'use strict';
        var self = this;

        self.TypeID = ko.observable(documentTypeID);

        self.PrivateComment = ko.observable(privateComment);
        self.Status = ko.observable(statusID);
        self.FirmID = ko.observable(firmID);
        self.VendorFirmID = ko.observable(vendorFirmID);
        self.InvoicePeriod = ko.observable(invoicePeriod);
        self.DatePayable = ko.observable(datePayable);
        self.InvoiceNumbers = ko.observable(invoiceNumber);

        self.DetailItems = ko.observableArray([]);

        self.isFinalized = ko.computed(function () {
            //finalized if it has the appropriate status (anything except)
        });


        self.hasPrivateComments = ko.computed(function () {
            // if self.privatecomment isn't null or empty, true
        });

        self.TotalFees = ko.computed(function () {
            //foreach item in detailitems, sum of fees.
        });

        self.TotalCosts = ko.computed(function () {
            //foreach item in detailitems, sum of Costs.

        });

        self.TotalAdjustments = ko.computed(function () {
            //foreach item in detailitems, sum of adjustments.

        });

        self.GrandTotal = ko.computed(function () {
            //foreach item in detailitems, sum of totals.

        });

    },

    LoadInvoice: function (clientSiteID, invoiceID, callbackFunction, errorFunction) {
        'use strict';
        var self = this;

        self.clientSiteID = clientSiteID;
        self.invoiceID = invoiceID;


        $.ajax({
            url: '/api/DefenseInvoice/GetDefenseInvoice?ClientSiteID=' + self.clientSiteID + "&InvoiceID=" + invoiceID,
            type: 'GET',
            processData: false,
            contentType: 'application/json; charset=utf-8',
            dataType: "json",
            data: null,
            success: function (data) {
                console.log(data);
                callbackFunction(data);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                errorFunction(jqXHR, textStatus, errorThrown);

            }
        });
    },

    ViewModel: function () {
        'use strict';
        var self = this;

        self.InvoiceLoaded = ko.observable();

        self.Invoice = ko.observable(new invoiceDetailsPage.Invoice()); // load blank invoice first

        self.clientSiteID = -1;
        self.invoiceID = -1;

        self.SaveInvoiceDetails = function () {
            // can only save the details prior to approval / rejection
            // should update only general invoice fields, not private comments or adjustments
        };

        self.LoadInvoice = function() {
            self.InvoiceLoaded(false);
            invoiceDetailsPage.LoadInvoice(self.clientSiteID, self.invoiceID, function(result) {
                //success
                vm.Invoice(new invoiceDetailsPage.Invoice(
                    result.InvoiceInfo.DefenseInvoiceID,
                    result.InvoiceDocumentTypeID,
                    result.InvoiceInfo.FirmID,
                    result.InvoiceInfo.InvoiceNumber,
                    result.InvoiceInfo.InvoicePeriod,
                    result.InvoiceInfo.DatePayable,
                    result.InvoiceInfo.PrivateComment,
                    result.InvoiceInfo.StatusID,
                    result.InvoiceInfo.VendorFirmID
                ));

                self.InvoiceLoaded(true);
            }, function() {
                //error
                toastr.error("We're sorry, but an error occurred while trying to load the invoice. Please contact support or refresh the page to try again.", "Invoice Approval");
                console.log("LoadInvoice -- ERROR");
                console.log("     error: " + errorThrown);
                toastr.clear(notifier);

            });
        };

        self.Start = function () {

            self.LoadInvoice();
        };
    },

    utils: {

        GetSelect2Options: function (placeholder, url) {
            'use strict';
            var options = {
                allowClear: false,
                placeholder: placeholder,
                query: function (query) {
                    var dto = {
                        query: query.term,
                        filters: {
                            ClientSiteID: Number(vm.clientSiteID)
                        }
                    };
                    $.ajax({
                        type: "POST",
                        url: url,
                        data: JSON.stringify(dto),
                        contentType: "application/json; charset=utf-8",
                        dataType: "json",
                        success: function (msg) {
                            query.callback(msg);
                        }
                    });
                }
            };
            return options;
        }
    }
};

使用している Knockout Binding

ko.bindingHandlers.select2 = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var obj = valueAccessor(),
            allBindings = allBindingsAccessor(),
            lookupKey = allBindings.lookupKey;
        $(element).select2(obj);
        if (lookupKey) {
            var value = ko.utils.unwrapObservable(allBindings.value);
            $(element).select2('data', ko.utils.arrayFirst(obj.data.results, function (item) {
                return item[lookupKey] === value;
            }));
        }

        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).select2('destroy');
        });
    },
    update: function (element) {
        $(element).trigger('change');
    }
};

HTML 要素とそのバインディング

<input type="text" id="ddlInvoiceType" placeholder="Invoice Type" class="select2-container" data-bind="select2: invoiceDetailsPage.utils.GetSelect2Options('Invoice Type', '/api/DefenseInvoiceType/Post'), value: Invoice().TypeID"/>
4

2 に答える 2

1

私はそれを機能させましたが、違いはselectのような初期化にあると思います

<input type="hidden" class=""
    data-bind="value: observedValue, select2: --your options--">

これが私のものです:

init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
    ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
        $(element).select2('destroy');
      });

      select2 = ko.utils.unwrapObservable(allBindings().select2);

  $(element).select2(select2);
},
于 2015-06-23T20:48:13.533 に答える
1

質問を正しく理解しているかどうかはわかりませんが、最初はカスタム バインディングの更新部分で問題が発生する可能性があります。

update: function (element, valueAccessor) {
  //added next row to update value
  $(element).val(ko.utils.unwrapObservable(valueAccessor()));

  $(element).trigger("change");
}
于 2013-11-12T15:52:53.650 に答える