2012-06-16 19 views
40

गतिशील रूप से जेनरेट किए गए तत्वों पर नॉकआउट डेटा-बाइंड काम करना संभव कैसे है? उदाहरण के लिए, मैं एक div के अंदर एक साधारण एचटीएमएल चयन मेनू डालता हूं और नॉकआउट विकल्प बाध्यकारी का उपयोग करके विकल्पों को पॉप्युलेट करना चाहता हूं। यह मेरा कोड जैसा दिखता है:गतिशील रूप से जेनरेट किए गए तत्वों पर नॉकआउट डेटा-बाइंड

$('#menu').html('<select name="list" data-bind="options: listItems"></select>'); 

लेकिन यह विधि काम नहीं करती है। कोई विचार?

+0

क्या आप इसे अपने ko.applyBindings (yourVMHere) करने के बाद जोड़ रहे हैं; – PlTaylor

+0

इस गतिशील रूप से जोड़े गए DOM तत्व पर बाध्यकारी (ऑटो) केओ के विचार को छोड़ दें और इसे मैन्युअल रूप से संभाल लें। – Vaibhav

उत्तर

30

यदि आप अपने व्यूमोडेल को बाध्य करने के बाद इस तत्व को फ्लाई पर जोड़ते हैं तो यह व्यूमोडेल में नहीं होगा और अपडेट नहीं होगा। आप दो चीजों में से एक कर सकते हैं।

  1. डोम के तत्व जोड़ें और यह ko.applyBindings(); फिर से कॉल
  2. द्वारा फिर से बाँध या शुरू से ही डोम के लिए सूची में जोड़ने के लिए और अपने viewmodel खाली में विकल्पों संग्रह छोड़ दें। जब तक आप फ्लाई पर विकल्पों में तत्व जोड़ते हैं, तब तक नॉकआउट इसे प्रस्तुत नहीं करेगा।
+11

यदि मैं लागू करता हूं तो बाइबिलिंग फिर से फेंकती है: त्रुटि: आप एक ही तत्व में बाइंडिंग को कई बार लागू नहीं कर सकते हैं। – Chris

+2

यह हालिया ढांचे की एक नई विशेषता होनी चाहिए। दूसरा विकल्प अभी भी व्यवहार्य है, और ईमानदारी से शुरू करने के लिए बेहतर विकल्प है। – PlTaylor

+1

हां मैंने जितना अधिक पाया, बाइंडिंग को एक तत्व पर एक बार लागू करने के लिए यह बुरा अभ्यास है। चूंकि यह 2 बार आग लग जाएगा, मुझे लगता है कि इसीलिए उन्होंने केओ 3 – Chris

3

संपादित करें: ऐसा लगता है कि इस के बाद से संस्करण 2.3 IIRC रूप से LosManos

बताया आप का उपयोग कर अपने दृश्य मॉडल के लिए एक और नमूदार जोड़ सकते हैं काम नहीं करता है myViewModel [newObservable] = ko.observable (' ')

उसके बाद, फिर से कॉल करें .apply बाइंडिंग्स।

यहां एक साधारण पृष्ठ है जहां मैं गतिशील रूप से पैराग्राफ जोड़ता हूं और नया दृश्य मॉडल और बाइंडिंग बेकार ढंग से काम करते हैं।

// myViewModel starts only with one observable 
 
    \t var myViewModel = { 
 
    \t  paragraph0: ko.observable('First') 
 
    \t }; 
 
    
 
    \t var count = 0; 
 
    
 
    \t $(document).ready(function() { 
 
    \t \t ko.applyBindings(myViewModel); 
 
    
 
    \t \t $('#add').click(function() { 
 
    \t \t \t // Add a new paragraph and make the binding 
 
    \t \t \t addParagraph(); 
 
    \t \t \t // Re-apply! 
 
    \t \t \t ko.applyBindings(myViewModel); \t \t \t 
 
    \t \t \t return false; \t 
 
    \t \t }); 
 
    \t }); 
 
    
 
    \t function addParagraph() { 
 
    \t \t count++; 
 
    \t \t var newObservableName = 'paragraph' + count; 
 
    \t  $('<p data-bind="text: ' + newObservableName + '"></p>').appendTo('#placeholder'); 
 
    \t \t 
 
    \t  // Here is where the magic happens 
 
    \t \t myViewModel[newObservableName] = ko.observable(''); 
 
    \t \t myViewModel[newObservableName](Math.random()); 
 
    
 
    \t \t // You can also test it in the console typing 
 
    \t \t // myViewModel.paragraphXXX('a random text') 
 
    \t }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script> 
 

 
<div id="placeholder"> 
 
    <p data-bind="text: paragraph0"></p> 
 
</div> 
 
    
 
<a id="add" href="#">Add paragraph</a>

+7

में कुछ चेतावनी जोड़ दी है कॉलिंग लागू करना एक से अधिक बार बाइंडिंग एक अच्छा विचार नहीं है। – gliljas

+0

@ gunteman..hy क्यों नहीं? – lamarant

+3

ऐसा लगता है कि "दो बार बाइंडिंग लागू नहीं कर सकता" त्रुटि फेंकती है। क्या यह ko.applyBindings() को एक बहुत ही विशिष्ट तत्व बताना है जिसे आप बाइंडिंग में जोड़ना चाहते हैं? – Chris

0

पर this existing answer आधार पर, मैं कुछ इसी तरह हासिल किया है अपने प्रारंभिक इरादों को:

function extendBinding(ko, container, viewModel) { 
    ko.applyBindings(viewModel, container.children()[container.children().length - 1]); 
} 

function yourBindingFunction() { 
    var container = $("#menu"); 
    var inner = $("<select name='list' data-bind='options: listItems'></select>"); 
    container.empty().append(inner); 


    extendBinding(ko, container, { 
     listItems: ["item1", "item2", "item3"] 
    }); 
} 

यहाँ एक JSFiddle साथ खेलने के लिए है।

चेतावनी दी जाए, एक बार जब नया तत्व डोम का हिस्सा हो, तो आप इसे ko.applyBindings पर कॉल के साथ फिर से बाध्य नहीं कर सकते - यही कारण है कि मैं container.empty() का उपयोग करता हूं। यदि आपको नए तत्व को संरक्षित करने और इसे दृश्य मॉडल परिवर्तन के रूप में बदलने की आवश्यकता है, तो extendBinding विधि के viewModel पैरामीटर पर एक अवलोकन योग्य पास करें।

10

एचटीएमएल बाध्यकारी कोड को फिर से लिखें या एक नया बनाएँ। एचटीएमएल बाध्यकारी क्योंकि रोकता है "इंजेक्शन बाइंडिंग" गतिशील html में:

ko.bindingHandlers['html'] = { 
 
    //'init': function() { 
 
    // return { 'controlsDescendantBindings': true }; // this line prevents parse "injected binding" 
 
    //}, 
 
    'update': function (element, valueAccessor) { 
 
    // setHtml will unwrap the value if needed 
 
    ko.utils.setHtml(element, valueAccessor()); 
 
    } 
 
};

+3

इस धागे पर सभी उत्तरों और टिप्पणियों को देखने के बाद, आईएमओ यह वास्तव में "गतिशील रूप से जेनरेट किए गए तत्वों पर नॉकआउट डेटा-बाइंड" प्रश्न का सबसे अच्छा समाधान है। अच्छा समाधान! – MattSizzle

1

यह एक पुराने सवाल है, लेकिन यहाँ है मेरी उम्मीद है कि अप-टू-डेट जवाब (नॉकआउट 3.3.0):

प्रीबाउंड अवलोकन योग्य संग्रह में तत्व जोड़ने के लिए नॉकआउट टेम्पलेट्स या कस्टम घटकों का उपयोग करते समय, नॉकआउट स्वचालित रूप से सबकुछ बाध्य करेगा। आपका उदाहरण मेनू आइटमों के एक अवलोकन संग्रह की तरह दिखता है जो बॉक्स के बाहर काम करेगा।

10

नॉकआउट 3।3

ko.bindingHandlers.htmlWithBinding = { 
      'init': function() { 
      return { 'controlsDescendantBindings': true }; 
      }, 
      'update': function (element, valueAccessor, allBindings, viewModel, bindingContext) { 
       element.innerHTML = valueAccessor(); 
       ko.applyBindingsToDescendants(bindingContext, element); 
      } 
    }; 

से ऊपर कोड स्निपेट आप "htmlWithBinding" संपत्ति के साथ प्रभावी ढंग से HTML तत्वों इंजेक्षन कर सकते हैं। जोड़े गए तत्वों का मूल्यांकन भी किया जाता है ... यानी उनके डेटा-बाइंड गुण।

ko.bindingHandlers['dynamicHtml'] = { 
    'update': function (element, valueAccessor, allBindings, viewModel, bindingContext) { 
     // setHtml will unwrap the value if needed 
     ko.utils.setHtml(element, valueAccessor()); 
     ko.applyBindingsToDescendants(bindingContext, element); 
    } 
}; 
3

v3.4.0 के लिए कस्टम नीचे बंधन का उपयोग करें।

संबंधित मुद्दे