94

パーミッションUIを構築しています。パーミッションのリストがあり、各パーミッションの横に選択リストがあります。権限は、選択リストにバインドされているオブジェクトの監視可能な配列によって表されます。

<div data-bind="foreach: permissions">
     <div class="permission_row">
          <span data-bind="text: name"></span>
          <select data-bind="value: level, event:{ change: $parent.permissionChanged}">
                   <option value="0"></option>
                   <option value="1">R</option>
                   <option value="2">RW</option>
           </select>
      </div>
 </div>

ここで問題となるのは、UIが初めて入力されたときに変更イベントが発生することです。ajax関数を呼び出し、パーミッションリストを取得すると、パーミッションアイテムごとにイベントが発生します。これは本当に私が望む振る舞いではありません。ユーザーが選択リストで権限の新しい値を実際に選択した場合にのみ発生させたいのですが、どうすればよいですか?

4

11 に答える 11

120

実際には、イベントが user または program によってトリガーされるかどうかを調べたいと思います。初期化中にイベントがトリガーされることは明らかです。

追加のノックアウト アプローチはsubscription、ほとんどのモデルでこのように実装されるため、すべての場合に役立つわけではありません。

  1. モデルを未定義のデータで初期化します。構造だけです (actual KO initilization)
  2. モデルを初期データで更新する (logical init like load JSON , get data etc)
  3. ユーザー インタラクションとアップデート

キャプチャしたい実際のステップは 3 の変更ですが、2 番目のステップでsubscriptionは call を取得します。

 <select data-bind="value: level, event:{ change: $parent.permissionChanged}">

permissionChanged関数でイベントを検出しました

this.permissionChanged = function (obj, event) {

  if (event.originalEvent) { //user changed

  } else { // program changed

  }

}
于 2013-12-05T10:35:48.810 に答える
32

これはあくまでも推測ですが、数値なのでそうなっていると思いますlevel。その場合、valueバインディングは文字列値でchange更新するイベントをトリガーします。したがって、が最初の文字列であるlevelことを確認することで、これを修正できます。level

さらに、これを行うより「ノックアウト」な方法は、イベント ハンドラーを使用せず、オブザーバブルとサブスクリプションを使用することです。オブザーバlevelブルを作成し、それにサブスクリプションを追加します。サブスクリプションは、level変更されるたびに実行されます。

于 2012-06-20T01:51:00.930 に答える
4

この奇妙な動作に役立つ可能性のある解決策を次に示します。変更イベントを手動でトリガーするボタンを配置するよりも良い解決策を見つけることができませんでした。

編集:このようなカスタムバインディングが役立つかもしれません:

ko.bindingHandlers.changeSelectValue = {

   init: function(element,valueAccessor){

        $(element).change(function(){

            var value = $(element).val();

            if($(element).is(":focus")){

                  //Do whatever you want with the new value
            }

        });

    }
  };

そして、select data-bind 属性に以下を追加します。

changeSelectValue: yourSelectValue
于 2012-06-18T09:04:38.750 に答える
3

私はこのカスタム バインディングを使用します ( RP Niemeyer によるこのフィドルに基づいています。この質問に対する彼の回答を参照してください)。これにより、数値が文字列から数値に適切に変換されます (Michael Best のソリューションで示唆されています)。

Javascript:

ko.bindingHandlers.valueAsNumber = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var observable = valueAccessor(),
            interceptor = ko.computed({
                read: function () {
                    var val = ko.utils.unwrapObservable(observable);
                    return (observable() ? observable().toString() : observable());
                },
                write: function (newValue) {
                    observable(newValue ? parseInt(newValue, 10) : newValue);
                },
                owner: this
            });
        ko.applyBindingsToNode(element, { value: interceptor });
    }
};

HTML の例:

<select data-bind="valueAsNumber: level, event:{ change: $parent.permissionChanged }">
    <option value="0"></option>
    <option value="1">R</option>
    <option value="2">RW</option>
</select>
于 2013-06-13T10:12:25.830 に答える
2

プリミティブ値の代わりにオブザーバブルを使用すると、select は初期バインディングで変更イベントを発生させません。オブザーバブルに直接サブスクライブするのではなく、変更イベントにバインドし続けることができます。

于 2013-01-25T17:51:01.333 に答える
1

シンプルなフラグを使用して、すばやくダーティにします。

var bindingsApplied = false;

var ViewModel = function() {
    // ...

    this.permissionChanged = function() {
        // ignore, if flag not set
        if (!flag) return;

        // ...
    };
};

ko.applyBindings(new ViewModel());
bindingsApplied = true; // done with the initial population, set flag to true

これが機能しない場合は、setTimeout() で最後の行をラップしてみてください。イベントは非同期であるため、applyBindings() が既に返されたときに最後の行がまだ保留されている可能性があります。

于 2012-06-18T07:11:56.767 に答える
0

同様の問題があり、イベントハンドラーを変更して変数の型を確認しました。タイプは、ページが最初にロードされたときではなく、ユーザーが値を選択した後にのみ設定されます。

self.permissionChanged = function (l) {
    if (typeof l != 'undefined') {
        ...
    }
}

これは私にはうまくいくようです。

于 2014-05-30T15:41:13.107 に答える
-1

js コンポーネントを作成する

define([
    'Magento_Ui/js/form/element/select',
    'mage/translate'
], function (AbstractField, $t) {
    'use strict';

    return AbstractField.extend({
        defaults: {
            imports: {
                update: 'checkout.steps.shipping-step.shippingAddress.shipping-address-fieldset.country_id:value'
            },
            modules: {
                vat_id: '${ $.parentName }.vat_id'


            }
        },

        /**
         * Initializes UISelect component.
         *
         * @returns {UISelect} Chainable.
         */
        initialize: function () {
            this._super();
            this.vat_id().visible(false);
            return this;
        },
        update: function (value) {
            if(value == 'GB'){
                this.vat_id().visible(true);
            }else{
                this.vat_id().visible(false);

            }
        }
        
        
            
         
      
    });
});
于 2021-01-20T12:49:15.117 に答える