ProgramingTip

KnockoutJs v2.3.0 : 오류 동일한 요소에 바인딩을 여러 번 적용 할 수 없습니다.

bestdevel 2020. 10. 23. 08:11
반응형

KnockoutJs v2.3.0 : 오류 동일한 요소에 바인딩을 여러 번 적용 할 수 없습니다.


2.3.0으로 업그레이드 한 경우 이제 오류가 발생합니다.

동일한 요소에 바인딩을 여러 번 적용 할 수 없습니다.

나는 2.2.1에 들어 가지 않았다.

내 MVC 컨트롤러에서 부분보기를 href를 클릭 한 후 페이지에 추가합니다. 발생하는 오류는 부분보기를 위해 링크를 두 번째로 클릭 할 때 발생합니다. 나는 여러 번하고있다.

관리자 지우고 새로운 오류가 발생하지 않도록하는 방법이 있습니까?

내 코드는 다음과 달라집니다.

$.get(url + "GetAssignedCompaniesView?layoutId=" + layoutId + "&noCache=" + new Date().getMilliseconds(), function (result) {
              $("#editAssignedPartial").html($(result));
              showEditAssignedArea(true);
              $(window.document).ready(function () {
                 // error is thrown here
                 ko.applyBindings(self, window.document.getElementById("editAssigned"));
                 $("#layoutId").attr("value", layoutId);
                 updateTypeHiddenElement.attr("value", "companies");
      });
    });
<div id="editAssignedPartial">
</div>

$(document).ready(function () {
  'use strict';
  var vm = new Vm();
  ko.applyBindings(vm, document.getElementById("area1"));
});

'applyBindings'를 다시 사용하기 전에 바인딩을 제거하기 만하면됩니다.

ko.cleanNode($element[0]);

트릭을해야합니다. HTH.


이 예외를 발생시키는 일도 보관 수있는 것은 다음과 같습니다. 당신이 가지고있는 것이 :

ko.applyBindings(myViewModel1, document.getElementById('element1'));
...
ko.applyBindings(myViewModel2, document.getElementById('element2'));

이제 # element1과 # element2가 모두 존재하지 오류가 발생합니다. 그 이유는 # element1을 사용할 수 없을 때 Knockout의 applyBindings가 document.body에서 루트 요소로 대체되기 때문입니다. 이제 바디에 바인딩을 두 번 적용합니다 ...

나에게 물어 보면 Knockout의 좋은 대체가 아닙니다. 오히려 요소가 아직 DOM에 존재하지 않는다는 명확한 오류 메시지가 표시됩니다.

이것이 어떤 사람들에게 도움이되기를 바랍니다.


위의 솔루션이 작동 예상 두 가지가 중요합니다.

  1. 바인딩을 적용 할 때 범위 (요소)를 지정해야합니다 !!

  2. 바인딩을 지울 때 범위에 사용하는 것과 동일한 것과 동일한 요소를 지정합니다.

코드는 다음과 가변적입니다.

마크 업

<div id="elt1" data-bind="with: data">
    <input type="text" data-bind="value: text1" >
</form>

바인딩보기

var myViewModel = {
  "data" : {
    "text1" : "bla bla"
  }
}:

자바 펼쳐

ko.applyBindings(myViewModel, document.getElementById('elt1'));

바인딩 지우기

ko.cleanNode(document.getElementById('elt1'));

뷰에 바인딩을 두 번 이상 적용 가능성. 2.2에서는 동작이 정의되지 않았는데 여전히 지원되지 않습니다. 2.3에서는 이제 오류가 표시됩니다. 녹아웃을 사용할 때 목표는 페이지의 뷰에 바인딩을 한 번 적용한 다음 뷰 모델의 옵저버 블에 대한 변경 사항을 사용하여 페이지에서 뷰의 모양과 동작을 변경하는 것입니다.


이 문제에 대한 훌륭한 답변이 많이 멍청한 답변이 있습니다.

실수로 확장을 두 곳에 추가 두 번 바인딩하려고했습니다. 뽑기 전에 간단한 실수로 머리카락을 확인하십시오.


마침내 바인딩 처리기 { controlsDescendantBindings: true }init기능으로 돌아가서 내 문제를 해결했습니다 . 참조


요소를 반복해서 재사용하는 경우 (제 경우에는 부트 스트랩 모달 대화 상자) ko.applyBindings(el)여러 번 호출 하면이 문제가 발생합니다.

대신 다음과 같이 한 번만 수행하십시오.

if (!applied) {
    ko.applyBindings(el);
    applied = true;
}

또는 다음과 같이 :

var apply = function (viewModel, containerElement) {
    ko.applyBindings(viewModel, containerElement);
    apply = function() {}; // only allow this function to be called once.
}

추신 : 매핑 플러그인을 사용하고 JSON 데이터를 관찰 할 수 있습니다.


다른 원인이 오류가 발생했습니다.

페이지 상단과 하단에 표시하고 싶은 저장 / 취소 버튼 템플릿을 만들었습니다. 처음에는 <script type = "text / html"> 요소 내부에 템플릿을 정의 할 때 작동했지만 일반 DIV 요소에서 템플릿을 선택적으로 만들 수 있습니다.

(이는 ASP.NET MVC를 사용하고 있었기 때문에 @variableName Razor 구문이 펼쳐지기 때문에 내부에서 실행에 실행되지 않는 갑자기 발생하기 때문에 더 잘 작동했습니다. 대신 DIV로 변경하여 MVC Razor 엔진을 사용할 수 있습니다. 페이지가로드 될 때 내 KnockoutJs 템플릿 유전자 HTML을 생성합니다.)

SCRIPT 요소 대신 DIV를 사용하도록하는 템플릿을 변경 한 후 코드는 다음과 같이 보였습니다. IE10에서 제대로 작동했습니다. 그러나 나중에 IE8 에서 테스트했을 때 던졌습니다.

"동일한 요소에 바인딩을 여러 번 적용 할 수 없습니다." 오류 .....

HTML

<div id="mainKnockoutDiv" class="measurementsDivContents hourlyMeasurements">

  <div id="saveButtons_template" style="display: none;">
    ... my template content here ...
  </div>

  <!--ko template: { name: 'saveButtons_template' } -->
  <!--/ko-->

  Some_HTML_content_here....

  <!--ko template: { name: 'saveButtons_template' } -->
  <!--/ko-->

</div>

자바 펼쳐

ko.applyBindings(viewModel, document.getElementById('mainKnockoutDiv'));

해결책 :

내가해야 할 일은 saveButtons_template DIV를 맨 아래로 이동하여 mainKnockoutDiv 외부에 추가하는 것입니다. 이것은 나를 위해 문제를 해결했습니다.

KnockoutJs가 applyBindings 대상 영역 내에 있고 SCRIPT 요소를 사용하지 않았기 때문에 템플릿 DIV를 여러 번 바인딩하려고 시도했다고 가정합니다 .... 템플릿으로 참조되었습니다.


IE7 / IE8에서 동일한 오류가 발생했습니다. IE9 / IE10을 포함한 다른 모든 브라우저에서 잘 작동했습니다.

내가 찾은 것은 자동 닫힘 태그를 제거하는 것입니다.

나쁜

<div>
    <span data-bind="text: name"/>
</div>

좋은

<div>
    <span data-bind="text: name"></span>
</div>

제 경우에는 존재하지 않는 요소에 추가했거나 존재할 수있는 요소에 바인딩을 추가했지만 부모는 그렇지 않았습니다. 이와 비슷합니다.

var segDiv =  $("#segments"); //did not exist, wrong id
var theDiv = segDiv.html("<div></div>");

ko.applyBindings(someVM, theDiv);

내가 말할 수있는 한,이 오류는 존재하지 않는 것과 같이 요소에서 발생할 수있는 많은 다른 오류에서 발생한다는 점에서 약간 오버로드 된 것 같습니다. 따라서 오류 설명은 매우 기만적 일 수 있습니다. 아마도 읽어야합니다.

"바인딩을 요소에 바인딩하는 데 실패했습니다. 가능한 이유는 여러 바인딩 시도, 요소가 존재하지 않음, DOM 계층 구조에없는 요소, 브라우저의 문제 등입니다."


업데이트 된 답변

이제 dataFor()바인딩이 적용되었는지 확인하는 데 사용할 수 있으므로 cleanNode()보다 데이터 바인딩을 확인하는 것이 좋습니다 applyBindings().

이렇게 :

var koNode = document.getElementById('formEdit');
var hasDataBinding = !!ko.dataFor(koNode);
console.log('has data binding', hasDataBinding);
if (!hasDataBinding) { ko.applyBindings(vm, koNode);}

원래 답변.

이미 많은 답변!

먼저 한 페이지에서 바인딩을 여러 번 수행해야하는 것이 매우 일반적이라고 가정 해 보겠습니다. 예를 들어, 부트 스트랩 모달 내부에 양식이 있으며 반복해서로드됩니다. 대부분의 양식 입력에는 양방향 바인딩이 있습니다.

나는 보통 쉬운 길을 택합니다 : 바인딩 전에 매번 바인딩을 지우는 것입니다.

var koNode = document.getElementById('formEdit');
ko.cleanNode(koNode);
ko.applyBindings(vm, koNode);

에서 생략 할 수 있지만 노드 요소 koNode가 필요하기 때문에 여기 에 필수 인지 확인하십시오 .ko.cleanNode()ko.applyBinding(vm)


나는 같은 문제가 있었고 그것을 해결했습니다.

var vm = new MessagesViewModel()
ko.applyBindings(vm)

function ShowMessagesList() {
   vm.getData("MyParams")
}

setInterval(ShowMessagesList, 10000)

ko.cleanNode($("#modalPartialView")[0]);
ko.applyBindings(vm, $("#modalPartialView")[0]);

나를 위해 작동하지만 다른 사람들이 지적했듯이 cleanNode내부 ko기능이므로 더 나은 방법이 있습니다.

참고 URL : https://stackoverflow.com/questions/17710788/knockoutjs-v2-3-0-error-you-cannot-apply-bindings-multiple-times-to-the-same-e

반응형