2012-12-09 21 views
13

में एकाधिक-इनपुट वर्चुअल विशेषताओं को ले जाएं डेटाबेस में ऊंचाई में संग्रहित किया जाता है।सरलफॉर्म कस्टम इनपुट घटक

हालांकि फुट और इंच रूप में अपने स्वयं के व्यक्तिगत आदानों की जरूरत है:

Height: [_______] feet [_______] inches 

तो मैं आभासी विशेषताओं का इस्तेमाल किया, और काम मिल गया।

class Client < ActiveRecord::Base 
    attr_accessible :name, :height_feet, :height_inches 

    before_save :combine_height 

    def height_feet 
     height.floor/12 if height 
    end 

    def height_feet=(feet) 
     @feet = feet 
    end 

    def height_inches 
     if height && height%12 != 0 
     height%12 
     end 
    end 

    def height_inches=(inches) #on save? 
     @inches = inches 
    end 

    def combine_height 
    self.height = @feet.to_d*12 + @inches.to_d #if @feet.present? 
    end 

end 

और _form आंशिक simple_form का उपयोग कर:

<%= simple_form_for(@client) do |f| %> 
    <ul> 
    <%= f.error_notification %> 
    <%= f.input :name %> 
    <%= f.input :weight %> 
    <li> 
     <%= f.input :height_feet, :label => 'Height', :wrapper => false %> 
     <span>feet</span> 
     <%= f.input :height_inches, :label => false, :wrapper => false %> 
     <span>inches</span> 
    </li> 
    <%= f.error :base %> 
    </ul> 
    <%= f.button :submit %> 
<% end %> 

यह काम करता है यहाँ मेरी मॉडल का एक सरलीकृत संस्करण है। लेकिन यह आदर्श नहीं है।

मैं इस सूख और एक custom input component तो मैं <%= f.input :height, as: :feet_and_inch %> -और इसलिए किसी भी अन्य इनपुट कि एक ही पैटर्न <%= f.input :wingspan, as: :feet_and_inch %> के रूप में इस तरह के इस प्रकार के साथ फार्म के लिए ऊंचाई में जोड़ सकते हैं बनाना चाहते हैं।

मैं और इसी तरह कस्टम घटकों के साथ प्रयोग किया है, लेकिन मैं दो आदानों के लिए नहीं मिल सकता है प्रदर्शित-और मुझे यकीन है कि जहां फुट और इंच इंच से 'रूपांतरण' तर्क डाल करने के लिए सबसे अच्छी जगह है नहीं कर रहा हूँ (इंच से पैरों और इंच तक)।

+0

एक साधारण सहायक विधि का उपयोग क्यों नहीं करते? मेरे लिए कस्टम इनपुट घटक जोड़ने की कोई आवश्यकता नहीं है ... और फॉर्म निर्माता प्राप्त करने वाला एक सहायक तरीका, आपको जो चाहिए, वह करने के लिए सबसे सरल और सबसे DRY तरीका है। :) और रूपांतरण तर्क के लिए, यह इस बात पर निर्भर करता है कि आप उन तर्कों का उपयोग कहां करते हैं ... यदि यह केवल विचारों में है, तो उन्हें सहायक तरीके से रखें, अन्यथा मॉडल एक अच्छी जगह है। – Kulgar

+0

एक छोटे से गहरे खुदाई करने के कारणों में से एक यह है कि वर्तमान कार्यान्वयन में त्रुटि संदेशों को पैर और इंच इनपुट के बीच प्रदर्शित किया जाता है, दोनों के बाद, उन्हें एक सहायक विधि में ले जाना हल नहीं होगा इस। वैसे, इनपुट के लिए धन्यवाद! – bookcasey

+0

यदि कोई दिलचस्पी लेता है, तो यह इतना सिरदर्द साबित हुआ कि मैंने '5'10" ',' 5'11 "', '6'' जैसे विकल्पों के साथ एक एकल चयन तत्व का उपयोग करने का निर्णय लिया, जिसमें' वैल ' इंच (70,71,72) में सेट करें जो थोड़ा लूप के साथ करना मुश्किल नहीं था। – bookcasey

उत्तर

6

जहां तक ​​मुझे पता है, आप वास्तव में कुछ भी नहीं ले जा सकते हैं लेकिन कस्टम इनपुट को प्रतिपादन कर सकते हैं। फॉर्म सबमिट होने के बाद सरलफॉर्म को कॉल नहीं किया जाता है, इसलिए यह किसी भी तरह से मूल्यों में वास्तव में हस्तक्षेप नहीं कर सकता है। मुझे इसके बारे में गलत होना पसंद है क्योंकि मुझे अतीत में भी इसकी आवश्यकता थी। वैसे भी, यहां एक संस्करण है जो मॉडल में रूपांतरण तर्क रखता है।

कस्टम SimpleForm इनपुट:

# app/inputs/feet_and_inch_input.rb 
class FeetAndInchInput < SimpleForm::Inputs::Base 
    def input 
    output   = "" 
    label   = @options.fetch(:label) { @attribute_name.to_s.capitalize } 

    feet_attribute = "#{attribute_name}_feet".to_sym 
    inches_attribute = "#{attribute_name}_inches".to_sym 

    output << @builder.input(feet_attribute, wrapper: false, label: label) 
    output << template.content_tag(:span, " feet ") 
    output << @builder.input(inches_attribute, wrapper: false, label: false) 
    output << template.content_tag(:span, " inches ") 

    output.html_safe 
    end 

    def label 
    "" 
    end 
end 

प्रपत्र। ध्यान दें कि मैंने कस्टम इनपुट के अंदर <li> टैग नहीं डाले हैं, मुझे लगता है कि यह इस तरह से अधिक लचीला है लेकिन इसे बदलने में स्वतंत्र महसूस करें।

# app/views/clients/_form.html.erb 
<li> 
    <%= f.input :height, as: :feet_and_inch %> 
</li> 

यह सब तथ्य यह है कि हर height विशेषता के लिए, आप भी height_feet और height_inches गुण है पर निर्भर करता है।

अब मॉडल के लिए, मैं नहीं ईमानदारी से यकीन है कि अगर यह जाने के लिए, हो सकता है किसी को एक बेहतर समाधान ऊपर आ सकता है जिस तरह से है, लेकिन यहाँ यह जाता है:

class Client < ActiveRecord::Base 
    attr_accessible :name 

    ["height", "weight"].each do |attribute| 
    attr_accessible "#{attribute}_feet".to_sym 
    attr_accessible "#{attribute}_inches".to_sym 

    before_save do 
     feet = instance_variable_get("@#{attribute}_feet_ins_var").to_d 
     inches = instance_variable_get("@#{attribute}_inches_ins_var").to_d 

     self.send("#{attribute}=", feet*12 + inches) 
    end 

    define_method "#{attribute}_feet" do 
     value = self.send(attribute) 
     value.floor/12 if value 
    end 

    define_method "#{attribute}_feet=" do |feet| 
     instance_variable_set("@#{attribute}_feet_ins_var", feet) 
    end 

    define_method "#{attribute}_inches=" do |inches| 
     instance_variable_set("@#{attribute}_inches_ins_var", inches) 
    end 

    define_method "#{attribute}_inches" do 
     value = self.send(attribute) 
     value % 12 if value && value % 12 != 0 
    end 
    end 
end 

यह मूल रूप से एक ही है, लेकिन परिभाषित करता है गतिशील रूप से तरीकों। आप शीर्ष पर देख सकते हैं कि विशेषताओं की एक सूची है जिसके लिए आप इन विधियों को उत्पन्न करना चाहते हैं।

ध्यान दें कि यह सब वास्तव में पूरी तरह से परीक्षण नहीं किया गया है और आपकी बिल्ली को मार सकता है लेकिन उम्मीद है कि आप कुछ विचार दे सकते हैं।

+0

मुझे लगता है कि यह एक अच्छा समाधान है, बिल्कुल चालाक विचार। –

2

मेरी विनम्र राय यह है कि यदि उपयोगकर्ता केवल एक फ़ील्ड में डेटा इनपुट करता है तो आप बेहतर उपयोगकर्ता अनुभव देंगे। यहां मेरी चिंताओं हैं:

मान लीजिए कि आप सीमित सीमा (शायद मानव की ऊंचाई) में ऊंचाई का उपयोग कर रहे हैं, तो आप एक सत्यापन लिख सकते हैं जो उपयोगकर्ता इनपुट - इंच या पैरों का पता लगाता है। फिर आप एक सत्यापन लिंक (या एक बटन बेहतर) पूछ सकते हैं कि इनपुट क्या है (इंच या पैरों का पता चला)।

यह सब (आयाम परिवर्तन सहित यह केवल इंच -> फीट सहित) जावास्क्रिप्ट में किया जा सकता है, आप अजाक्स कॉल द्वारा वर्तमान आयाम ला सकते हैं और पृष्ठ के पूरे कोड को पुनः लोड करने से बच सकते हैं।

संपादित करें: मुझे जटिल इनपुट से संबंधित interesting point of view मिला है। पैर और इंच के साथ फ़ॉर्म भरने में उपयोगकर्ता इंटरैक्शन के बारे में एक और useful resource

आपका प्रश्न वास्तव में दिलचस्प है और मुझे आपके द्वारा चुने गए समाधान को देखना अच्छा लगेगा।

+0

मैंने इसके बारे में बहुत कुछ सोचा है, और मुझे लगता है कि दो इनपुट यूएक्स आदर्श है, भले ही यह लागू करने के लिए अधिक कांटेदार हो। मैं व्यक्तिगत रूप से '' '' '' '(विशेष रूप से मोबाइल पर) के लिए कीबोर्ड के चारों ओर मछली के बजाय' 5' टैब '10' टाइप करना पसंद करूंगा, या उपयोगकर्ता को 5 फीट 10 इंच टाइप करने के लिए मजबूर करूंगा। मैं भी इस तरह जावास्क्रिप्ट आदर्श के बिना काम करने के लिए। आपके विचारों के लिए धन्यवाद! – bookcasey