[knockout.js] 녹아웃 바인딩으로 선택한 이벤트 변경, 실제 변경 사항인지 어떻게 알 수 있습니까?

권한 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가 처음으로 채워질 때 change 이벤트가 발생합니다. 내 ajax 함수를 호출하고 권한 목록을 가져온 다음 각 권한 항목에 대해 이벤트가 발생합니다. 이것은 내가 원하는 행동이 아닙니다. 나는 그것이 제기 할 사용자가 정말 선택 목록에서 권한에 대한 새 값에서 선택합니다 경우에만 나는 그렇게 할 수있는 방법?



답변

실제로 이벤트가 user 또는 program에 의해 트리거되는지 확인하고 초기화 중에 이벤트가 트리거된다는 것이 분명합니다.

추가의 녹아웃 방식이 subscription모든 경우에 도움이되는 것은 아닙니다. 대부분의 모델이 이와 같이 구현되기 때문입니다.

  1. 정의되지 않은 데이터로 모델을 초기화하고 구조 만 (actual KO initilization)
  2. 초기 데이터로 모델 업데이트 (logical init like load JSON , get data etc)
  3. 사용자 상호 작용 및 업데이트

캡처하려는 실제 단계는 3의 변경 사항이지만 두 번째 단계 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

  }

}


답변

이것은 추측 일 뿐이지 만 level숫자 이기 때문에 일어나는 것 같습니다 . 이 경우 value바인딩은 문자열 값 change으로 업데이트 할 이벤트를 트리거 level합니다. 따라서 level시작할 문자열 인지 확인하여이 문제를 해결할 수 있습니다 .

또한이를 수행하는보다 “녹아웃”방법은 이벤트 처리기를 사용하지 않고 관찰 가능 항목과 구독을 사용하는 것입니다. 확인 level관찰하고 때마다 실행 얻을 것이다, 그것에 구독을 추가 level변경.


답변

다음은이 이상한 동작에 도움이 될 수있는 솔루션입니다. 변경 이벤트를 수동으로 트리거하는 버튼을 배치하는 것보다 더 나은 솔루션을 찾을 수 없었습니다.

편집 : 아마도 이와 같은 사용자 지정 바인딩이 도움이 될 수 있습니다.

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
            }

        });

    }
  };

그리고 선택 데이터 바인딩 속성에 다음을 추가하십시오.

changeSelectValue: yourSelectValue


답변

이 사용자 지정 바인딩 ( RP Niemeyer 의이 바이올린을 기반 으로이 질문에 대한 답변 참조 )을 사용하여 숫자 값이 문자열에서 숫자로 올바르게 변환되는지 확인합니다 (Michael Best의 솔루션에서 제안한대로).

자바 스크립트 :

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>


답변

기본 값 대신 관찰 가능 항목을 사용하는 경우 선택은 초기 바인딩에서 변경 이벤트를 발생시키지 않습니다. Observable에 직접 구독하지 않고 변경 이벤트에 계속 바인딩 할 수 있습니다.


답변

간단한 플래그를 사용하여 빠르고 더럽습니다.

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 ()가 이미 반환되었을 때 마지막 줄이 여전히 보류 중일 수 있습니다.


답변

비슷한 문제가 있었고 변수 유형을 확인하기 위해 이벤트 처리기를 수정했습니다. 유형은 페이지가 처음로드 될 때가 아니라 사용자가 값을 선택한 후에 만 ​​설정됩니다.

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

이것은 나를 위해 일하는 것 같습니다.