0

データベースのテーブル行に基づいて構築されたオブジェクトがあります。そのエントリにあるすべてのプロパティに加えて、エントリ フィールドと表示されるものの間の中間層であるいくつかの ko.computed があります。一部のフィールド値の外部キーを変換できるようにする必要があります。

問題は次のとおりです。プロパティの 1 つが文字列の ID です。計算された ID を取得します。計算された値は次のようになります: 'option1|option2|option3|option4'

ユーザーがオプションを変更したり、新しいオプションを追加したり、それらを交換したりできるようにしたいのですが、ユーザーが何をしているかを監視する必要もあります (少なくとも、1 つのプロパティを追加、削除、または移動するとき)。したがって、ユーザーのアクションを監視できるようにバインドする監視可能な配列を作成しました。次に、配列は計算されたものにサブスクライブするため、データベースの値も更新されます。

コードの一部:

function Control(field) {
    var self = this;
    self.entry = field;  // database entry
    self.choices = ko.observableArray();
    self.ctrlType = ko.computed({
        read: function () {
           ...
        },
        write: function (value) {
            if (value) {
                ...
            }
        },
        owner: self
    });
    self.resolvedPropriety = ko.computed({
        read: function () {
            if (self.ctrlType()) {
                var options = str.split('|');
                self.choices(createObservablesFromArrayElements(options));
        return str;
            }
            else {
                return '';
            }
        },
        write: function (value) {
            if (value === '') {
                //delete entry      
            }
            else {
                    //modify entry
            }
        },
        deferEvaluation: true,
        owner: self
    });
    self.choices.subscribe(function (newValue) {
        if (newValue.length !== 0) {
            var newStr = '';
            $.each(newValue, function (id, el) {
                newStr += el.name() + '|';
            });
            newStr = newStr.substring(0, newStr.lastIndexOf("|"));
            if (self.resolvedPropriety.peek() !== newStr) {
                self.resolvedPropriety(newStr);
            }
        }
    });
self.addChoice = function () {
    //user added an option
        self.choices.push({ name: ko.observable('new choice') });
    };
    self.removeChoice = function (data) {
    //user removed an option
        if (data) {
            self.choices.remove(data);
        }
    };
    ...
}

この組み合わせは機能しますが、私が望むようには機能しません。これは周期的な動作であり、トリガーの回数が多すぎます。データベースへの要求が多いため、これはユーザーのアクションに過負荷を与えています。

私は何が欠けていますか?または、それを行うより良い方法はありますか?

4

1 に答える 1

0

ノックアウトの計算された観測可能なドキュメントからの引用

...依存チェーンにサイクルを含めることは意味がありません。

私が投稿から解釈した基本的な機能:

  • フィールドの選択に基づいて、プロパティ/オプションのリストを表示します
  • 上記のプロパティ/オプションを編集する機能を持っている
  • プロパティ/オプションを追加する機能がある
  • プロパティ/オプションを削除する機能があります
  • プロパティ/オプションを並べ替える機能があります(そこにあります。テキストフィールドの端/端をクリックする必要があります)
  • 変更を保存する機能がある

そのため、機能のスケルトン例を提供しましたが、最後のものを除いて、@ JSfiddleデータベースに変更を適用する機能は、いくつかの方法で対処できます。接続のオーバーヘッドを犠牲にするつもりがない限り、変化するデータに計算またはサブスクリプションを含める必要はありません。データ (すべて 1 回のサービス呼び出しで収集できると想定) を適切なネストされた観察可能なビュー モデルにフォーマットし、適切な観察可能なビュー モデルを渡すことで、任意のko.computed.

JS :

 var viewModel = {
 availableFields : ko.observableArray([
    ko.observable({fieldId: 'Field1', 
                   properties: ko.observableArray([{propertyName: "Property 1.1"}])}),
    ko.observable({fieldId: 'Field2', 
                   properties: ko.observableArray([{propertyName:"Property 2.1"}, 
                                                   {propertyName:"Property 2.2"}])})]),

 selectedField: ko.observable(),

 addProperty: function() {
    var propertyCount = this.selectedField().properties().length;

    this.selectedField().properties.push({propertyName: "Property " + propertyCount})
 },
};

ko.applyBindings(viewModel);
$("#field-properties-list").sortable({
   update: function (event, ui) {
   //jquery sort doesnt affect underlying array so we have to do it manually          
   var children = ui.item.parent().children();
   var propertiesOrderChanges = [];
   for (var i = 0; i < children.length; ++i) {
     var child = children[i];
     var item = ko.dataFor(child);
     propertiesOrderChanges.push(item)
   }
   viewModel.selectedField().properties(propertiesOrderChanges);
 }
});

HTML :

<span>Select a field</span>

<select data-bind='foreach: availableFields, value: selectedField'>
 <option data-bind='text: $data.fieldId, value: $data'></option>
</select>

<div style="padding: 10px">
 <label data-bind='text: "Properties for " + selectedField().fieldId'></label>
<button data-bind='click: $root.addProperty'>Add</button>
<ul id='field-properties-list' data-bind='foreach: selectedField().properties'>
    <li style = "list-style: none;">
        <button data-bind="click: function() {  $root.selectedField().properties.remove($data) }">Delete</button>
        <input data-bind="value: $data.propertyName"></input>
    </li>
</ul>
</div>
于 2013-10-03T04:29:27.160 に答える