2012-02-10 20 views
23

मान लीजिए मैं इस तरह knockout.js टेम्पलेट है:knockout.js टेम्पलेट्स में अद्वितीय आईडी

<script type="text/html" id="mytemplate"> 
    <label for="inputId">Label for input</label> 
    <input type="text" id="inputId" data-bind="value: inputValue"/> 
</script> 

अगर मैं (पेज मैं एक ही आईडी के साथ कई जानकारी के साथ अंत पर कई स्थानों में इस टेम्पलेट प्रस्तुत करना और के साथ मान के लिए कई लेबल), जिनके खराब परिणाम हैं। विशेष रूप से, आईडी पर निर्भर सभी कोड ठीक से काम नहीं कर सकते हैं (मेरे मामले में मैं jquery.infieldlabel प्लगइन का उपयोग करता हूं जो एक ही आईडी के साथ कई इनपुट द्वारा भ्रमित हो जाता है)। जिस तरह से मैं अब इस समस्या का समाधान मैं मॉडल है कि मैं टेम्पलेट के लिए बाध्य करने के लिए अद्वितीय आईडी गुण जोड़ने है:

<script type="text/html" id="mytemplate"> 
    <label data-bind="attr: {for: id}>Label for input</label> 
    <input type="text" data-bind="attr: {id: id}, value: inputValue"/> 
</script> 

यह काम करता है, लेकिन यह बहुत ही सुंदर के बाद से मैं अपने मॉडल में इस कृत्रिम आईडी गुण है की जरूरत नहीं है इसका उपयोग किसी और चीज़ के लिए नहीं किया जाता है। मुझे आश्चर्य है कि यहां एक बेहतर समाधान है या नहीं।

उत्तर

61

एक विकल्प जो कि इस क्षेत्र पर निर्भर नहीं है कि बाध्यकारी डेटा को id संपत्ति पर सेट करता है, जिसे एक अवलोकन करने की आवश्यकता होगी।

ko.bindingHandlers.uniqueId = { 
    init: function(element, valueAccessor) { 
     var value = valueAccessor(); 
     value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter); 

     element.id = value.id; 
    }, 
    counter: 0, 
    prefix: "unique" 
}; 

ko.bindingHandlers.uniqueFor = { 
    init: function(element, valueAccessor) { 
     var value = valueAccessor(); 
     value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter); 

     element.setAttribute("for", value.id); 
    } 
}; 

आप इसे पसंद का प्रयोग करेंगे:

<ul data-bind="foreach: items"> 
    <li> 
     <label data-bind="uniqueFor: name">Before</label> 
     <input data-bind="uniqueId: name, value: name" /> 
     <label data-bind="uniqueFor: name">After</label> 
    </li> 
</ul> 

नमूना: http://jsfiddle.net/rniemeyer/JjBhY/

नमूदार कार्य करने के लिए एक संपत्ति जोड़ने के बारे में अच्छी बात यह है कि करने के लिए वापस भेजने के लिए जब आप इसे JSON में बदल जाते हैं है सर्वर, तो यह स्वाभाविक रूप से गायब हो जाएगा क्योंकि अवलोकन योग्य अपने अनचाहे मूल्य में बदल जाएगा।

+4

मैं दूसरा हूं। लेकिन क्या मैं परेशान हो सकता हूं और समस्या के थोड़ा और जटिल संस्करण पर सलाह मांग सकता हूं - जहां आपके पास रेडियो की एक जोड़ी है उदा। लेबल के रूप में "हां" और "नहीं", प्रत्येक एक एकल बूलियन को देखने योग्य, उदाहरण के लिए "सक्रिय है"। फिलहाल सभी 4 तत्व - 2 रेडियो और 2 लेबल - सभी एक ही आईडी प्राप्त करते हैं। रेडियो के जोड़े कई बार प्रकट होते हैं, इसलिए मैं प्रत्येक जोड़ी के लिए नॉकआउट बाध्यकारी के साथ एक अद्वितीय नाम विशेषता उत्पन्न कर रहा हूं, इसलिए मुझे वर्तमान जोड़ी के उस विशिष्ट नाम को आईडी में उपसर्ग करने में सक्षम होना चाहिए। –

+0

अद्वितीय आईडी के लिए आप डेटा-बाइंड = "attr: {for: 'status_' + $ index}" और डेटा-बाइंड = "attr: {id: 'status_' + $ index}" का भी उपयोग कर सकते हैं – viperguynaz

+0

आप भी इसका उपयोग कर सकते हैं डेटा-बाइंड = "attr: {for: 'status_' + $ index}" और डेटा-बाइंड = "attr: {id: 'status_' + $ index}" अद्वितीय आईडी के लिए। मौजूदा इंडेक्स आइटम के शून्य-आधारित इंडेक्स को संदर्भित करने के लिए $ अनुक्रमणिका। $ इंडेक्स एक अवलोकन योग्य है और जब भी आइटम की अनुक्रमणिका बदलती है (उदा।, यदि आइटम सरणी से जोड़ा या हटा दिया जाता है) अद्यतन किया जाता है। – viperguynaz

6

मैं अतीत में कुछ इस तरह किया है:

<ul data-bind="foreach: items"> 
    <li> 
     <label data-bind="uniqueFor: 'before'">Before</label> 
     <input data-bind="uniqueId: true, value: name" /> 
     <label data-bind="uniqueFor: 'after'">After</label> 
    </li> 
</ul> 

तो, यह सिर्फ बाध्यकारी ही incrementing ko.bindingHandlers.uniqueId.counter पर राज्य रखता है:

ko.bindingHandlers.uniqueId = { 
    init: function(element) { 
     element.id = ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter); 
    }, 
    counter: 0, 
    prefix: "unique" 
}; 

ko.bindingHandlers.uniqueFor = { 
    init: function(element, valueAccessor) { 
     var after = ko.bindingHandlers.uniqueId.counter + (ko.utils.unwrapObservable(valueAccessor()) === "after" ? 0 : 1); 
      element.setAttribute("for", ko.bindingHandlers.uniqueId.prefix + after); 
    } 
}; 

आप उन्हें पसंद का प्रयोग करेंगे। फिर, uniqueFor बाध्यकारी को यह जानने की जरूरत है कि यह सही आईडी कैसे प्राप्त करें, यह जानने के लिए फ़ील्ड के पहले या बाद में है या नहीं।

यहाँ नमूना: http://jsfiddle.net/rniemeyer/8KJD3/

तो अपने लेबल (एकाधिक आदानों शायद एक तालिका के अलग-अलग पंक्तियों में प्रत्येक लेबल से पहले बाध्य) अपने खेतों के पास नहीं थे, तो आप एक अलग रणनीति को देखने के लिए की आवश्यकता होगी।

+0

मैं उन पंक्तियों के साथ कुछ सोच रहा था भी, और यह निश्चित रूप से होगा मेरे मामले में काम करते हैं, लेकिन मुझे इस समाधान के बारे में क्या पसंद नहीं है यह है कि यह उस क्रम पर निर्भर करता है जिसमें टैग प्रदान किए जाते हैं। हालांकि कोड के लिए धन्यवाद, यह निश्चित रूप से विकल्पों में से एक है। –

+0

यदि आदेश एक चिंता है, तो यहां एक और विकल्प है: http://jsfiddle.net/rniemeyer/JjBhY/।यह समान है, लेकिन बाध्यकारी सेट एक "आईडी" संपत्ति संभवतः एक अवलोकन योग्य है। जो भी बाध्यकारी इसे पहले हिट करता है वह आईडी को अपडेट करेगा। अवलोकन करने योग्य फ़ंक्शन पर "आईडी" प्रॉपर्टी सेट करने के बारे में अच्छी बात यह है कि जब आप इसे JSON में बदलते हैं तो यह गायब हो जाएगा, क्योंकि आपको केवल अवलोकन योग्य के अनचाहे मूल्य के साथ ही छोड़ा जाएगा। –

+0

धन्यवाद, यह वही है जो मैं ढूंढ रहा था! क्या आप इसे उत्तर के रूप में पोस्ट करना चाहते हैं, इसलिए मैं इसे स्वीकार कर सकता हूं? –

3

मैं चयनित उत्तर का जवाब नहीं दे सकता, लेकिन मेरे पास कोड का एक उन्नत संस्करण है जो प्रति इनपुट मान के कई अद्वितीय आईडी का समर्थन करता है। यह http://drewp.quickwitretort.com/2012/09/18/0 पर अपने ब्लॉग पर है और यहाँ दोहराया:

ko.bindingHandlers.uniqueId = { 
    /* 
     data-bind="uniqueId: $data" to stick a new id on $data and 
     use it as the html id of the element. 

     data-which="foo" (optional) adds foo to the id, to separate 
     it from other ids made from this same $data. 
    */ 
    counter: 0, 
    _ensureId: function (value, element) { 

    if (value.id === undefined) { 
     value.id = "elem" + (++ko.bindingHandlers.uniqueId.counter); 
    } 

    var id = value.id, which = element.getAttribute("data-which"); 
    if (which) { 
     id += "-" + which; 
    } 
    return id; 
    }, 
    init: function(element, valueAccessor) { 
     var value = valueAccessor(); 
     element.id = ko.bindingHandlers.uniqueId._ensureId(value, element); 
    }, 
}; 

ko.bindingHandlers.uniqueFor = { 
    /* 
     data-bind="uniqueFor: $data" works like uniqueId above, and 
     adds a for="the-new-id" attr to this element. 

     data-which="foo" (optional) works like it does with uniqueId. 
    */ 
    init: function(element, valueAccessor) { 
     element.setAttribute(
     "for", ko.bindingHandlers.uniqueId._ensureId(valueAccessor(), element)); 
    } 
}; 

अब आप स्वत: आईडी के साथ एक रिकॉर्ड के लिए कई लेबल चेक बॉक्स हो सकता है:

<li data-bind="foreach: channel"> 
    <input type="checkbox" data-which="mute" data-bind="uniqueId: $data, checked: mute">  
    <label data-which="mute" data-bind="uniqueFor: $data">Mute</label> 

    <input type="checkbox" data-which="solo" data-bind="uniqueId: $data, checked: solo">  
    <label data-which="solo" data-bind="uniqueFor: $data">Solo</label> 
</li> 
संबंधित मुद्दे