wake-up-neo.com

KnockoutJs v2.3.0: Fehler Sie können Bindungen nicht mehrmals auf dasselbe Element anwenden

Ich habe gerade ein Upgrade auf 2.3.0 durchgeführt und erhalte jetzt die Fehlermeldung "Sie können Bindungen nicht mehrmals auf dasselbe Element anwenden." dass ich nicht in 2.2.1.

Ich erhalte eine Teilansicht von meinem MVC-Controller und füge sie der Seite hinzu, nachdem Sie auf eine Href geklickt haben. Der Fehler tritt auf, wenn ich zum zweiten Mal auf den Link klicke, um die Teilansicht zu erhalten. Ich mache das mehrmals.

Gibt es eine Möglichkeit, dies zu beheben und den neuen Fehler zu vermeiden?

Hier ist mein Code:

$.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"));
});
69
Aligned

Sie müssen nur die Bindungen entfernen, bevor Sie 'applyBindings' erneut verwenden.

ko.cleanNode($element[0]);

sollte den Trick tun. HTH.

92
vprasad

Etwas, das auch passieren kann und diese Ausnahme auslöst, ist das Folgende. Sagen Sie, Sie haben:

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

Wenn jetzt # element1 und # element2 nicht existieren, wird der Fehler angezeigt. Der Grund dafür ist, dass die applyBindings von Knockout auf document.body als Stammelement zurückgreift, wenn # element1 und # element2 nicht gefunden werden. Jetzt versucht es zweimal am Körper zu binden ...

Kein schöner Rückfall von Knockout, wenn Sie mich fragen. Ich hätte lieber eine klare Fehlermeldung, dass das Element (noch) nicht im DOM vorhanden ist.

Hoffe das hilft einigen Leuten.

20
Almer

Sie sollten Bindungen niemals mehr als einmal auf eine Ansicht anwenden. In 2.2 war das Verhalten undefiniert, aber immer noch nicht unterstützt. In 2.3 wird jetzt ein Fehler korrekt angezeigt. Wenn Sie die Option "Aussparen" verwenden, müssen Sie die Bindungen einmal auf Ihre Ansichten auf der Seite anwenden und dann Änderungen an Observables in Ihrem Ansichtsmodell verwenden, um das Erscheinungsbild und das Verhalten Ihrer Ansichten auf Ihrer Seite zu ändern. 

12
x0n

Für die oben genannten Lösungen sind zwei Dinge wichtig:

  1. Wenn Sie Bindungen anwenden, müssen Sie den Gültigkeitsbereich (Element) angeben.

  2. Beim Löschen von Bindungen müssen Sie genau dasselbe Element angeben, das für den Bereich verwendet wird.

Code ist unten

Markup

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

Verbindliche Ansicht

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

Javascript

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

Bindungen löschen

ko.cleanNode(document.getElementById('elt1'));
12
Mitja Gustin

Es gibt viele großartige Antworten für dieses Problem, aber ich habe eine Noobie-Antwort.

Ich stellte fest, dass ich versehentlich das gleiche Skript an zwei Stellen hinzugefügt hatte und es versuchte zweimal zu binden. Stellen Sie also sicher, dass Sie nach diesem Problem suchen, bevor Sie sich bei einem einfachen Fehler die Haare ausreißen. 

9
Pete

Ich löste schließlich meine, indem ich { controlsDescendantBindings: true } in der init-Funktion des Bindungshandlers zurückgab. Siehe this

5

Wenn Sie ein Element immer wieder verwenden (ein modifizierter Bootstrap-Dialog in meinem Fall), führt das mehrfache Aufrufen von ko.applyBindings(el) zu diesem Problem.

Stattdessen einfach einmal so machen:

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

Oder so:

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

PS: Dies kann für Sie häufiger vorkommen, wenn Sie das Mapping-Plugin verwenden und Ihre JSON-Daten in Observables konvertieren.

4
Jess

Antwort aktualisiert

Da wir nun dataFor() verwenden können, um zu prüfen, ob die Bindung angewendet wurde, würde ich die Datenbindung lieber als cleanNode() und applyBindings() prüfen.

So was:

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

Ursprüngliche Antwort.

Viele Antworten schon!

Nehmen wir zunächst an, dass es ziemlich üblich ist, dass wir die Bindung mehrmals auf einer Seite durchführen müssen. Angenommen, ich habe ein Formular im Bootstrap-Modal, das immer wieder geladen wird. Viele Formulareingaben sind bidirektional gebunden.

Normalerweise gehe ich den einfachen Weg: Die Bindung wird jedes Mal vor der Bindung gelöscht.

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

Stellen Sie sicher, dass hier koNode erforderlich ist, da ko.cleanNode() ein Knotenelement erfordert, obwohl wir es in ko.applyBinding(vm) weglassen können.

1
Blaise

In meinem Fall fügte ich ein nicht vorhandenes Element hinzu oder fügte Bindungen zu einem möglicherweise vorhandenen Element hinzu, aber das übergeordnete Element nicht. Ähnlich wie dies:

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

ko.applyBindings(someVM, theDiv);

Soweit ich das beurteilen kann, scheint dieser Fehler ein wenig überlastet zu sein in dem Sinne, dass er auf viele verschiedene Fehler abzielt, die mit dem Element auftreten können, als ob es nicht existiert. Daher kann die Fehlerbeschreibung sehr trügerisch sein. Es sollte wahrscheinlich gelesen haben:

"Fehler beim Binden von Bindungen an ein Element. Mögliche Gründe: Mehrere Bindungsversuche, Element nicht vorhanden, Element nicht in DOM-Hierarchie, Macken in Browsern usw."

1
Neoraptor

Ich hatte diesen Fehler aus einem anderen Grund.

Ich habe eine Vorlage zum Speichern/Abbrechen von Schaltflächen erstellt, die oben und unten auf der Seite angezeigt werden soll. Es funktionierte zuerst, als ich meine Vorlage in einem <script type = "text/html"> -Element definiert hatte .... aber dann hörte ich, dass Sie optional eine Vorlage aus einem normalen DIV-Element erstellen könnten. 

(Dies funktionierte für mich besser, da ich ASP.NET MVC verwendete und keine meiner @ variableName Razor-Syntax zur Laufzeit vom Skriptelement aus ausgeführt wurde. Wenn ich stattdessen zu einem DIV wechsle, könnte ich die MVC Razor-Engine verwenden generiere HTML in meiner KnockoutJs-Vorlage, wenn die Seite geladen wird.)

Nachdem ich meine Vorlage geändert hatte, um ein DIV-Element anstelle eines SCRIPT-Elements zu verwenden, sah mein Code folgendermaßen aus ... was auf IE10 gut funktioniert hat. Aber später als ich es auf IE8 getestet habe , warf es das ...

"Sie können Bindungen nicht mehrmals auf dasselbe Element anwenden" error .....

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>

JavaScript

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

DIE LÖSUNG :

Alles, was ich tun musste, war, mein saveButtons_template DIV nach unten zu verschieben, sodass es sich außerhalb des mainKnockoutDiv befand. Dies hat das Problem für mich gelöst. 

Ich nehme an, KnockoutJs hat mehrfach versucht, meine Vorlagen-DIV zu binden, da sie sich im Zielbereich applyBindings befanden ... und nicht das SCRIPT-Element verwendet ... und als Vorlage referenziert wurde.

1
ClearCloud8

Ich habe dieselbe Fehlermeldung in IE7/IE8 erhalten. Funktionierte in allen anderen Browsern einschließlich IE9/IE10.

Was ich für mich als funktionierend empfand, war das Entfernen selbstschließender Tags. 

Schlecht

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

Gut

<div>
    <span data-bind="text: name"></span>
</div>
1
Two Seeds
ko.cleanNode($("#modalPartialView")[0]);
ko.applyBindings(vm, $("#modalPartialView")[0]);

funktioniert für mich, aber wie andere feststellen, ist die cleanNode interne ko-Funktion, daher gibt es wahrscheinlich einen besseren Weg.

0
Muflix

ich hatte das gleiche Problem und habe es gelöst.

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

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

setInterval(ShowMessagesList, 10000)
0
javad hemati