Ответ 1
Вам просто нужно удалить привязки, прежде чем снова использовать "applyBindings".
ko.cleanNode($element[0]);
должен сделать трюк. НТН.
Я только что обновился до 2.3.0 и теперь получаю ошибку
Вы не можете применять привязки несколько раз к одному и тому же элементу.
что я не получил в 2.2.1.
Я получаю частичное представление от моего контроллера MVC и добавляю его на страницу после нажатия на ссылку. Ошибка происходит во второй раз, когда я нажимаю на ссылку, чтобы получить частичное представление. Я делаю это несколько раз.
Есть ли способ убрать это и избежать новой ошибки?
Вот мой код:
$.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]);
должен сделать трюк. НТН.
Что-то, что может произойти, и которое вызывает это исключение, следующее. Скажите, что у вас есть:
ko.applyBindings(myViewModel1, document.getElementById('element1'));
...
ko.applyBindings(myViewModel2, document.getElementById('element2'));
Теперь, когда оба элемента # element1 и # element2 не существуют, вы получите ошибку. Причина в том, что Knockout applyBindings возвращается к document.body как к корневому элементу, когда # element1 и # element2 не найдены. Теперь он пытается применить привязку дважды на теле...
Не замечательный запас нокаута, если вы спросите меня. Я предпочел бы ясное сообщение об ошибке, что элемент не существует в DOM (пока).
Надеюсь, это поможет некоторым людям.
Вы не должны применять привязки более одного раза к представлению. В 2.2 поведение было undefined, но все еще не поддерживается. В 2.3 теперь он корректно показывает ошибку. При использовании нокаута цель состоит в том, чтобы применить привязки один раз к вашим представлениям на странице, а затем использовать изменения для наблюдаемых в вашей модели просмотра, чтобы изменить внешний вид и поведение вашего вида (ов) на вашей странице.
Для работы над решениями важны две вещи:
При применении привязок вам нужно указать область (элемент)!!
При очистке привязок вы должны указать точно такой же элемент, который используется для области видимости.
Код ниже
Разметка
<div id="elt1" data-bind="with: data">
<input type="text" data-bind="value: text1" >
</form>
Вид привязки
var myViewModel = {
"data" : {
"text1" : "bla bla"
}
}:
Javascript
ko.applyBindings(myViewModel, document.getElementById('elt1'));
Очистить привязки
ko.cleanNode(document.getElementById('elt1'));
Есть много отличных ответов для этой проблемы, но у меня есть ответ noobie.
Я обнаружил, что я случайно добавил тот же самый Script в два места, и он пытался связать дважды. Поэтому, прежде чем вытащить волосы на простую ошибку, убедитесь, что вы проверяете эту проблему.
Я наконец решил свою проблему, вернув { 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.
}
PS: Это может случиться чаще, если вы используете плагин сопоставления и преобразуете данные JSON в наблюдаемые.
У меня возникла эта ошибка по другой причине.
Я создал шаблон для кнопок сохранения/отмены, которые я хотел бы показать вверху и внизу страницы. Сначала он работал, когда у меня был мой шаблон, определенный внутри типа < script type = "text/html" > element.... но потом я слышал, что вы могли бы при необходимости создать шаблон из обычного элемента DIV.
(Это работало лучше для меня с тех пор, как я использовал ASP.NET MVC, и ни один из синтаксиса @variableName Razor не выполнялся во время выполнения изнутри элемента script. Поэтому, перейдя на DIV, я все равно мог иметь двигатель MVC Razor генерировать HTML внутри моего шаблона KnockoutJs, когда страница загружается.)
После того, как я изменил свой шаблон для использования DIV вместо элемента script, мой код выглядел так..., который отлично работал на 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>
JavaScript
ko.applyBindings(viewModel, document.getElementById('mainKnockoutDiv'));
РЕШЕНИЕ:
Все, что мне нужно было сделать, - это переместить мой saveButtons_template DIV вниз, чтобы он находился вне mainKnockoutDiv. Это решило проблему для меня.
Я предполагаю, что KnockoutJs пытался связать мой шаблон DIV несколько раз, так как он находился внутри целевой области applyBindings... и не использовал элемент script.... и ссылался как на шаблон.
Я получал ту же ошибку в IE7/IE8. Работала отлично во всех других браузерах, включая IE9/IE10.
То, что я нашел, работало для меня - это устранение закрывающих тегов.
Bad
<div>
<span data-bind="text: name"/>
</div>
Хорошо
<div>
<span data-bind="text: name"></span>
</div>
Теперь, когда мы можем использовать 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);}
Уже много ответов!
Во-первых, допустим, довольно часто нам нужно выполнять привязку несколько раз на странице. Скажем, у меня внутри формы Bootstrap есть форма, которая будет загружаться снова и снова. Многие из форм ввода имеют двустороннюю привязку.
Я обычно выбираю легкий путь: очищать привязку каждый раз перед привязкой.
var koNode = document.getElementById('formEdit');
ko.cleanNode(koNode);
ko.applyBindings(vm, koNode);
Просто убедитесь, что здесь требуется koNode
, поскольку для ko.cleanNode()
требуется элемент узла, хотя мы можем опустить его в ko.applyBinding(vm)
.
В моем случае я добавлял к несуществующему элементу, или я добавлял привязки к элементу, который, возможно, существует, но родитель этого не сделал. Аналогично этому:
var segDiv = $("#segments"); //did not exist, wrong id
var theDiv = segDiv.html("<div></div>");
ko.applyBindings(someVM, theDiv);
Насколько я могу судить, эта ошибка кажется немного перегруженной в том смысле, что она срабатывает по множеству различных ошибок, которые могут произойти с элементом, например, он не существует. Таким образом, описание ошибки может быть очень обманчивым. Вероятно, он должен был читать:
"Невозможность привязки привязки к элементу Возможные причины включают в себя: попытки множественного связывания, элемент не существующий, элемент не в иерархии DOM, причуды в браузерах и т.д.
У меня была та же проблема, и я решил ее.
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
, так что, возможно, есть лучший способ.