0

読み取り専用の電話番号のテーブルがあります。電話番号には、番号とタイプ (携帯電話や自宅など) があります。各電話番号には [編集] ボタンがあり、クリックすると、電話番号を編集してモーダル ダイアログに入力できます。読み取り専用テーブルとエディターに Knockoutjs を使用しています。テーブルは observableArray にバインドされPhoneVMs、エディターは単一の で動作しPhoneVMます。ユーザーが変更を適用する前にモーダルで [OK] をクリックする必要があるため、モーダルは選択したもののコピーで機能し、 [OK] をクリックすると、テーブルがバインドされている observableArray でPhoneVM最初にクリックされたものを置き換えますPhoneVM. それはすべてうまくいっています。

ここで、リストの最初の電話を読み取り専用テーブルと同じページで (モーダルなしで) 編集できるようにする必要があります。ワークフローの早い段階で最初の電話を入力しやすくするためのアイデアです。そのため、ページに電話を入力すると、下の読み取り専用リストに自動的に表示され、通常どおりモーダルで編集することもできます. Knockout なら簡単にできると思っていたのですが、思わぬ障害にぶつかりました。この時点から、何がうまくいかないかの例を示す方が簡単です。このフィドルで次の操作を行います: https://jsfiddle.net/ph4mhsof/

  1. 電話番号を編集し、テキスト ボックスからタブで移動します。[すべての電話] リストの最初の電話も更新されることに注意してください。
  2. ドロップダウンで電話の種類を変更します。[すべての電話] テーブルで、タイプ ID とタイプ名の両方が適切に変更されていることに注意してください。
  3. [最初の電話を削除] をクリックします。2 台目の電話機が新しい 1 台目の電話機になります。
  4. 電話番号を編集し、テキスト ボックスからタブで移動します。[すべての電話] リストの最初の電話が期待どおりに更新されることに注意してください。
  5. ドロップダウンで電話の種類を変更します。All Phones リストの Type ID だけが更新されていることに注意してください。タイプ名は更新されません。

カスタムバインディングを使用して、タイプ名を選択のテキストにバインドしています。そのバインディングの init 関数の valueAccessor は、元の最初の PhoneVM のPhoneTypeNameプロパティを特に指している必要があるようですが、私がそれを行う必要があるのは、firstPhone計算されたプロパティのPhoneTypeName. これを修正する方法はありますか?

元の jsfiddle のコピー:

function phoneListVM() {
  var _self = this;
  this.phones = ko.observableArray([
    new phoneVM(1, "Mobile", "123-234-3456"),
    new phoneVM(2, "Home", "654-343-3211")
  ]);

  this.firstPhone = ko.computed(function() {
    return _self.phones()[0];
  });
}

function phoneVM(typeID, typeName, Number) {
  this.PhoneTypeID = ko.observable(typeID);
  this.PhoneTypeName = ko.observable(typeName);
  this.PhoneNumber1 = ko.observable(Number);
}

ko.bindingHandlers.selectedTextValue = {
  init: function(element, valueAccessor) {
    var value = valueAccessor();

    $(element).change(function() {
      value($("option:selected", this).text());
    });
  },
  update: function(element, valueAccessor) {}
};

$(document).ready(function() {
  var phoneList = new phoneListVM()
  ko.applyBindings(phoneList);
  $("button").click(function() {
    phoneList.phones.shift();
  });
});
.editor{
  background-color:rgba(200,200,250, 0.2);
  border: 1px solid rgba(0,0,0, 0.2);
  padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<h4>
Edit First Phone
</h4>
<div class="editor">
  <p>Phone Number:
    <input data-bind="value: firstPhone().PhoneNumber1" />
  </p>
  <p>Phone Type:
    <select data-bind="value:firstPhone().PhoneTypeID, selectedTextValue:firstPhone().PhoneTypeName">
      <option value="0"></option>
      <option value="1">Mobile</option>
      <option value="2">Home</option>
    </select>
  </p>
</div>

<h4>
All Phones
</h4>
<table>
  <thead>
    <tr>
      <th>Type ID</th>
      <th>Type Name</th>
      <th>Number</th>
    </tr>
  </thead>
  <tbody data-bind="foreach:phones">
    <tr>
      <td><span data-bind="text:PhoneTypeID"></span></td>
      <td><span data-bind="text:PhoneTypeName"></span></td>
      <td><span data-bind="text:PhoneNumber1"></span></td>
    </tr>
  </tbody>
</table>
<button type="button">
  Remove First Phone
</button>

4

3 に答える 3

0

customBinding はやり過ぎだという他の 2 つの回答に同意します。しかし、コードを簡単に変更できないとおっしゃったように、私はあなたの問題を示します。

カスタム バインド宣言では、関数を定義したばかりですが、init関数をupdate空白のままにしています。それが問題です。選択ボックスに変更を加えると、changeイベントが発生しますが、イベント ハンドラーがないため、何も起こりません。

実際、カスタム バインディングはchangeイベント ハンドラーを選択ボックスに正常に追加しました。そのため、最初の電話番号を削除する前であれば問題ありません。ただし、イベントの選択ボックスに追加できるイベント ハンドラーは 1 つだけであるため、最初の電話番号を削除すると、イベント ハンドラーが削除されますchange

解決策は次のinitとおりです。関数を空白のままにして、現在のすべての関数の内容を次のように関数に移動しinitますupdate

ko.bindingHandlers.selectedTextValue = {
  init: function(element, valueAccessor) {

  },
  update: function(element, valueAccessor) {
    var value = valueAccessor();

    $(element).change(function() {
      value($("option:selected", this).text());
    });
  }
};
于 2017-10-18T01:36:11.397 に答える