it-swarm.asia

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"));
});
71
Aligned

عليك فقط إزالة الروابط قبل استخدام "ApplyBindings" مرة أخرى.

ko.cleanNode($element[0]);

يجب أن تفعل الخدعة. HTH.

96
vprasad

الشيء الذي يمكن أن يحدث كذلك والذي يلقي هذا الاستثناء هو ما يلي. قل لديك:

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

الآن ، في حالة عدم وجود كل من # element1 و # element2 ، فستتلقى الخطأ. السبب هو أن تطبيق Knockout'sBindings يرجع إلى document.body كعنصر أساسي عندما لا يتم العثور على # element1 و # element2. الآن يحاول تطبيق الربط مرتين على الجسم ...

لا لطيفة احتياطي بالضربة القاضية إذا سألتني. أفضل رسالة خطأ واضحة تفيد بأن العنصر غير موجود في DOM (حتى الآن).

آمل أن يساعد هذا بعض الناس.

21
Almer

يجب عدم تطبيق الارتباطات أكثر من مرة على طريقة عرض. في 2.2 ، كان السلوك غير محدد ، ولكن لا يزال غير مدعوم. في 2.3 ، يظهر الآن خطأ بشكل صحيح. عند استخدام الضربة القاضية ، يكون الهدف هو تطبيق الارتباطات مرة واحدة على طريقة العرض الخاصة بك على الصفحة ، ثم استخدام التغييرات للملاحظات على نموذج العرض لتغيير مظهر وسلوك طريقة العرض الخاصة بك على صفحتك.

12
x0n

شيئان مهمان لحلول أعلاه للعمل:

  1. عند تطبيق الروابط ، تحتاج إلى تحديد نطاق (عنصر)!

  2. عند مسح الروابط ، يجب عليك تحديد نفس العنصر المستخدم للنطاق بالضبط.

الرمز أدناه

Markup

<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'));
12
Mitja Gustin

هناك الكثير من الإجابات الرائعة لهذه المشكلة ، لكن لدي إجابة noobie.

لقد وجدت أنني قمت عن طريق الخطأ بإضافة نفس البرنامج النصي في مكانين وكان يحاول الربط مرتين. لذا ، قبل أن تسحب شعرك بخطأ بسيط ، تأكد من التحقق من هذه المشكلة.

9
Pete

لقد حللت أخيرًا من خلال إرجاع { controlsDescendantBindings: true } في init ظيفة معالج الربط. انظر هذا

5
Martin Lottering

إذا كنت تعيد استخدام عنصر مرارًا وتكرارًا (مربع حوار مشروط للتمهيد في حالتي) ، فإن استدعاء 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 الخاصة بك إلى الملاحظات.

4
Jess

تحديث الإجابة

والآن بعد أن أصبح بإمكاننا استخدام 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).

1
Blaise

في حالتي ، كنت أقوم بإضافة عنصر غير موجود ، أو كنت أقوم بإضافة روابط إلى عنصر ربما كان موجودًا ، لكنه الأصل لم يكن موجودًا. مشابهة لهذه:

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

ko.applyBindings(someVM, theDiv);

بقدر ما أستطيع أن أقول ، يبدو أن هذا الخطأ مثقل بعض الشيء بمعنى أنه سيطلق الكثير من الأخطاء المختلفة التي يمكن أن تحدث مع العنصر ، كما هو غير موجود. على هذا النحو ، يمكن أن يكون وصف الخطأ خادعًا للغاية. ربما كان يجب أن يقرأ:

"الفشل في ربط الروابط بالعنصر. الأسباب المحتملة تشمل: محاولات ربط متعددة ، عنصر غير موجود ، عنصر غير موجود في التسلسل الهرمي DOM ، المراوغات في المتصفحات ، إلخ"

1
Neoraptor

لقد حدث هذا الخطأ لسبب مختلف.

لقد قمت بإنشاء قالب لأزرار الحفظ/الإلغاء التي أردت أن تظهر في أعلى وأسفل الصفحة. لقد نجحت في البداية عندما تم تحديد القالب الخاص بي داخل عنصر <script type = "text/html"> .... ولكن بعد ذلك سمعت أنه يمكنك إنشاء قالب من عنصر DIV عادي بدلاً من ذلك.

(لقد كان هذا الأمر أفضل بالنسبة لي منذ أن كنت أستخدم ASP.NET MVC ولم يتم تنفيذ أي من بناء جملة RazorvariableName الخاص بي في وقت التشغيل من داخل عنصر البرنامج النصي. لذلك من خلال التغيير إلى 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>

جافا سكريبت

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

الحل :

كل ما كان علي فعله هو تحريك saveButtons_template DIV الخاص بي إلى أسفل ، بحيث كان خارج mainKnockoutDiv. هذا حل المشكلة بالنسبة لي.

أفترض أن KnockoutJs كان يحاول ربط DIV بالقالب الخاص بي عدة مرات لأنه كان موجودًا داخل منطقة الهدف applicationBindings ... ولم يكن يستخدم عنصر SCRIPT .... وكان يتم الرجوع إليه كقالب.

1
ClearCloud8

كنت أتلقى نفس الخطأ في IE7/IE8. عملت بشكل جيد في جميع المتصفحات الأخرى بما في ذلك IE9/IE10.

ما وجدته يعمل بالنسبة لي كان التخلص من علامات إغلاق النفس.

سيئة

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

حسن

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

يصلح لي ، ولكن كما لاحظ آخرون ، cleanNode هي وظيفة ko داخلية ، لذلك ربما هناك طريقة أفضل.

0
Muflix

عانيت من نفس المشكلة وقمت بحلها.

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

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

setInterval(ShowMessagesList, 10000)
0
javad hemati