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


87

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

답변:


107

실제로 이벤트가 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

  }

}

5
나는 이것이 정답으로 표시되어야한다고 생각합니다. 질문에 설명 된대로 정확한 시나리오가 있었고 문자열을 select요소에 대한 키로 전달하는 것을 테스트했습니다 . 그러나 선택의 초기 값이 옵션 중 하나와 일치하더라도 여전히 change이벤트를 트리거했습니다 . if핸들러 에서이 간단한 블록을 구현했을 때 모든 것이 예상대로 작동했습니다. 이 방법을 먼저 시도하십시오. 감사합니다, @Sarath!
Pflugs

사용자 변경과 프로그램 변경을 구분하는 개념이 마음에 듭니다. 이는 특히 관찰 가능 항목이 사용자 상호 작용없이 값을 변경할 가능성이 가장 높은 녹아웃과 같은 일상적인 경우에 유용합니다.
rodiwa

@Pflugs에 동의하여 저에게 효과가있는 이벤트 유형을 구분하고 이것이 허용되는 대답이어야합니다.
Emma Middlebrook

1
def는 허용 된 답변이어야합니다 ... 이벤트 유형 속성을 사용하여
premissionChanged

1
또한이 방법을 사용하여 사용자가 다른 트리거가 아닌 선택 항목을 변경했는지 여부를 감지했습니다. 필자의 경우 "옵션"바인딩을 통해 옵션 값을 업데이트하면 "변경"이벤트가 트리거되었습니다.
nath

32

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

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


페이지로드 후 '변경'이벤트를 트리거하는 내 양식의 원인을 2 시간 동안 파헤친 후, 당신은 저를 구한 것 같습니다.
Samih A

귀하의 답변은 나에게 아이디어를주었습니다 ... 의도적으로 URL에서 오는 유형을 변경했기 때문에 구독 기능이 페이지로드시 트리거됩니다 (드롭 다운이 변경을 트리거했을 때뿐만 아니라 url var을 처리하기를 원했습니다). 이 작업을 수행하는 덜 해커 방법이 있습니까?
Jiffy

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
            }

        });

    }
  };

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

changeSelectValue: yourSelectValue

오 ... 당신은 버튼을 막아처럼 의미 .. 나를 위해 좋지 않다 ... 난 정말 그냥 :) 작업이 필요합니까?
남자 쉘러

더 나은 솔루션으로 답변을 수정하세요.
Ingro

Ingro, 이것은 답변이 아닌 것으로 (잘못) 표시되었습니다. 신고자가 실수로 질문을 답변으로 게시한다고 생각하지 않도록 초기 문장을 변경했습니다. 도움이 되었기를 바랍니다! :)
jmort253 2013

@ jmort253 : 죄송합니다, 그건 내 잘못이었습니다. "나도 같은 문제가 있습니다."라고 대답하지 않는 것이 좋습니다. 다른 질문을하는 것 같습니다. 대신 답변에 대한 해결책을 직접 제공하고 작동 방식을 설명하십시오.
Qantas 94 Heavy

1
네, 미안 해요, 제 실수입니다. 그것은 내가 stackoverflow에 게시 한 첫 번째 답변 중 하나 였고 모든 규칙을 알지 못했습니다. 편집 해 주셔서 감사합니다!
Ingro

3

이 사용자 지정 바인딩 ( 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>

2

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


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


안녕하세요, 회신 해 주셔서 감사합니다. dom이 준비되었을 때 ko.applyBindings를 호출하기 때문에 이것이 작동하지 않을 것입니다. 문제는 여전히 발생할 것입니다.
guy schaller

0

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

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

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


0

이것을 사용하십시오 :

this.permissionChanged = function (obj, event) {

    if (event.type != "load") {

    } 
}

0

이걸로 해봐:

self.GetHierarchyNodeList = function (data, index, event)
{
    debugger;
    if (event.type != "change") {
        return;
    }        
} 

event.type == "change"
event.type == "load" 

두 번째 매개 변수는 색인이 아니 었습니다. 저에게는 이벤트였습니다.
sairfan

@sairfan 함수에 몇 가지 매개 변수를 추가하고 디버거를 사용하여 이벤트를 얻는 매개 변수를 찾습니다.
Chanaka Sampath

-1

녹아웃을 사용하여 작업하는 경우 관찰 가능한 기능 녹아웃의 주요 기능을 사용하십시오. 메서드를
사용 ko.computed()하고 해당 함수 내에서 ajax 호출을 수행하고 트리거합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.