18

jQTouch Web アプリケーションでのデータバインディングを容易にするために、ノックアウトとノックアウト マッピング プラグインを使用しています。マッピング プラグインを使用する理由は、javascript でビューモデルを手動で定義/変更する必要なくノックアウトを使用できるようにするためです。マッピング プラグインは、サーバー/クライアント側のデータベースからデータを最初にロードするときに最適に機能します。

私たちが抱えている問題は、初期データが存在しない可能性があるフォームを持ついくつかの画面/ビューがあることです。この初期データがないと、マッピング プラグインはビューモデル (ko.mapping.fromJS) を「生成」できません。これは、ビューの大部分に対して手動でビューモデルを定義する必要があることを意味します。

これがマッピング プラグインがサポートする (すべき) シナリオであると仮定するのは間違っていますか? つまり、これは、マッピング プラグインが、常にデータの初期ロードがあるシナリオでのみ使用できることを意味します。

4

3 に答える 3

19

ビューモデルを手動で管理するだけでなく、いくつかのオプションがあります。マッピング プラグインは、create作成方法をカスタマイズできるコールバックをサポートしています。これを使用して、オブジェクトに既定のプロパティを追加することができます。

このようなもの: http://jsfiddle.net/rniemeyer/WQGVC/

もう 1 つの方法は、不足しているプロパティを作成するバインディングを使用することです。次のようになります。

//create an observable if it does not exist and populate it with the input's value
ko.bindingHandlers.valueWithInit = {
    init: function(element, valueAccessor, allBindingsAccessor, data) {
        var property = valueAccessor(),
            value = element.value;

        //create the observable, if it doesn't exist 
        if (!ko.isWriteableObservable(data[property])) {
            data[property] = ko.observable();
        }

        //populate the observable with the element's value (could be optional)
        data[property](value);

        ko.applyBindingsToNode(element, { value: data[property] });
    }
}

次のように使用します (プロパティを文字列として渡す必要があります。そうしないと、エラーが発生します)。

<input data-bind="valueWithInit: 'name'" />

サンプルはこちら: http://jsfiddle.net/rniemeyer/JPYLp/

于 2011-07-18T18:59:21.367 に答える
4

あなたの問題の解決策は、ビューモデルを間違った方法で考えることにあると思います。ビュー モデルは、データをビューに配信するだけでなく、データを送信するためのプレース ホルダーでもあります。

私が通常ノックアウトで作業する方法では、空のビューモデルをビューに送信することはありません。ビューモデルには通常、私がバインドしているすべてのフィールドがあります。それらは空の文字列、または表示値のない初期化されたオブジェクトである可能性がありますが、実際のオブジェクトはまだ存在し、バインドしているフィールドへの各オブジェクトの適切な表現があります。

ビューに何も送信するのではなく、単に空のオブジェクトを送信することを検討することをお勧めします。

編集: 例は un ASP.NET MVC です

基本的に、サーバー側で、表示する必要があるすべてのデータと収集する必要があるすべてのデータを含むビュー モデル オブジェクトを作成します。検証コードを簡単にするために、通常、収集するデータを独自のサブクラスに入れますが、それはすべてコードのニーズの問題です。

いずれにせよ、ビューに送られるすべてのオブジェクトは、オブジェクトの JSON シリアル化を生成する toJSON() メソッドを基本的に提供する vmBase クラスから継承されます。これは、ビュー エンジンによって私のビューで呼び出されます。以下のコードに示すように。

      <script type='text/javascript'>         
        var viewModel = ko.mapping.fromJS(<%= Model.ToJson() %>);                     

        $(document).ready( function () {        
            ko.applyBindings(viewModel);                             
        });                  
     </script>   

コードを元に戻す準備ができたら、ビュー モデルの JS バージョンのプルを削除するだけです。

<script type='text/javascript'>
     var dataToSendToServer = ko.toJS(viewModel);
</script>

ビューモデルの一部のみが変更されている一部のサナリオ (これは AJAX 更新を行っている場合) では、テンプレートを切り替えて別のバインディングを適用できるようにするなどのクールなことを行うことができます。この場合、元のデータ/テンプレートのコンテナーとして#ID_of_Containerを使用し、テンプレート (data-bind="" 要素を含むことができる) を新しいテンプレートID_of_Templateに置き換えます。

<script type='text/javascript'>
    ko.cleanNode($("#ID_of_Container"));
    delete (viewModel.Some_Element_To_Be_Updated);
    viewModel = ko.mapping.updateFromJS(viewModel, New_Data_For_That_Element);

    // Use ko.toJS(viewModel) because standard template plugin doesn't understand 
    // knockout observables
    $("#ID_of_Container").html($("#ID_of_Template").tmpl(ko.toJS(viewModel)))
    ko.applyBindings(viewModel, $("#ID_of_Container")[0]);

</script>
于 2011-07-20T11:00:27.213 に答える
0

私が現在検討しているアプローチの 1 つは、ReturnEmptyObject() という追加の Web サービス メソッドを作成することです。このメソッドは、サーバー側で新しくインスタンス化されたオブジェクト (プロパティは既定値になります) を作成して返すだけです。(私の場合は C#) オブジェクトは JSON にシリアル化され、最終的に jQuery Ajax 呼び出しに到着します....そして ko.mapping.updateFromJS()... に渡され、最初のページの読み込み時に必要なオブザーバブルが作成されます.. . ko.applyBindings() を呼び出す前に。

ko.applyBindings() が実行されると、必要なオブザーバブルが見つかるため、それらがほとんど空であってもエラーはスローされません。

このようにして、フィールドに何も入力せずにページを最初に開くことができます。ただし、サーバー側のクラスにいくつかの新しいプロパティを追加すると、それらはクライアント側に自動的に表示されます。

于 2013-02-28T23:53:59.243 に答える