रेल 3: "फ़ील्ड-विद-एरर्स" आवरण पृष्ठ की उपस्थिति को बदल देता है। इससे कैसे बचा जाए?


131

ईमेल फ़ील्ड:

<label for="job_client_email">Email: </label> 
<input type="email" name="job[client_email]" id="job_client_email">

इस तरह दिखता है:

बिना किसी त्रुटि के

लेकिन, यदि ईमेल सत्यापन विफल हो जाता है, तो यह हो जाता है:

<div class="field_with_errors">
  <label for="job_client_email">Email: </label>
</div> 
<div class="field_with_errors">
  <input type="email" value="wrong email" name="job[client_email]" id="job_client_email">
</div>

जो इस तरह दिखता है:

with_error

मैं इस रूप परिवर्तन से कैसे बच सकता था?


हाय @ misha-moroshko, मैं यहाँ वर्णित के रूप में मूल स्तर पर त्रुटि वर्ग जोड़ने की कोशिश करते हैं । मैंने बाईबॉग का उपयोग करके रेल कोड में गोता लगाने की कोशिश की लेकिन मैं तुरंत खो गया था .. मैं इस व्यवहार को थोड़ा स्मार्ट तरीके से जांचना चाहता था कि क्या उन क्षेत्र में माता-पिता हैं ..
SanjiBukai

जवाबों:


235

आपको ओवरराइड करना चाहिए ActionView::Base.field_error_proc। वर्तमान में इसे इस प्रकार परिभाषित किया गया है ActionView::Base:

 @@field_error_proc = Proc.new{ |html_tag, instance| 
   "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
 }

आप इसे अपने एप्लिकेशन की कक्षा में इसे डालकर ओवरराइड कर सकते हैं config/application.rb:

config.action_view.field_error_proc = Proc.new { |html_tag, instance| 
  html_tag
}

इस परिवर्तन को प्रभावी करने के लिए रीस्टेल सर्वर को पुनः आरंभ करें।


4
एक छोटा सा सवाल: क्यों labelऔर दोनों inputलिपटे हुए हैं? रेल्स कैसे तय करें कि क्या लपेटें?
मीशा मोरोस्को

4
यह शायद इसलिए किया जाता है ताकि आप किसी फ़ील्ड के लेबल को त्रुटियों के साथ भी स्टाइल कर सकें। इसके अलावा, रेल जानता है कि क्या रैप करने के लिए, क्योंकि आप इसे बताओ जो खेतों संसाधन की क्या विशेषता अपने लिए प्रपत्र बना रहे हैं से संबंधित हैं: f.label :passwordऔर f.password_field :passwordमें @resource.errorsएक होगा [:password]त्रुटि सेट।
मॉसेलमैन

3
यदि आप ट्विटर बूटस्ट्रैप के साथ काम कर रहे हैं, या आप एक और उदाहरण चाहते हैं कि आप field_error_proc में क्या कर सकते हैं, तो इस भयानक जिस्ट की जाँच करें
Ryan Sandridge

2
कोई "# {html_tag}" क्यों करेगा। html_safe, और html_tag.html_safe नहीं?
अनुराग

3
अनुराग: अगर html_tag शून्य हो जाता है, या एक स्ट्रिंग के अलावा कुछ भी होता है, तो एक सादा html_tag.html_safe एक त्रुटि उत्पन्न करेगा। इसे "# {html_tag}" में डाल देना संक्षेप में html_tag.to_s कहता है, जो उम्मीद है कि एक स्ट्रिंग लौटाएगा, जो तब
html_safe

100

आप जो दृश्य अंतर देख रहे हैं वह इसलिए हो रहा है क्योंकि divतत्व एक ब्लॉक तत्व है। एक इनलाइन तत्व की तरह व्यवहार करने के लिए इस शैली को अपनी CSS फ़ाइल में जोड़ें:

.field_with_errors { display: inline; }

2
यह सबसे अच्छा एक हैक है क्योंकि यह जो भी display:संपत्ति (और अन्य लेआउट शैलियों) का इस्तेमाल किया जा रहा है उसे नकारता है html_tag
रियान

1
मैं इसे हैक के रूप में नहीं देखता। displayपहले इस सीएसएस जोड़ा जाता है संपत्ति इस्तेमाल किया जा रहा blockहै जो दृश्य अंतर यह है कि वांछित नहीं है खड़ी कर रहा है। यह टैग पर किसी भी अन्य लेआउट शैलियों की उपेक्षा नहीं करता है। हालाँकि, यदि आप उस टैग को बदलना / हटाना चाहते हैं जो त्रुटियों के साथ फ़ील्ड को हटाता है, तो रेयान बिग्ग का उत्तर एकदम सही है।
नॉटैंगग

मैंने यह कोशिश की, हालांकि, अगर आपके फ़ील्ड्स <p> टैग्स के अंदर हैं, तो यह <p> टूटने के बाद से <div> के भीतर काम करना कम से कम (फ़ायरफ़ॉक्स पर नहीं) काम नहीं करता है। Biggs के समाधान का उपयोग करते हुए, केवल <span के साथ <div को प्रतिस्थापित करना चाल को लगता है।
जेपीडब्ल्यू

72

मैं वर्तमान में इस सॉल्यूशन का उपयोग करता हूं, इनिशियलाइज़र में रखा गया है:

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  class_attr_index = html_tag.index 'class="'

  if class_attr_index
    html_tag.insert class_attr_index+7, 'error '
  else
    html_tag.insert html_tag.index('>'), ' class="error"'
  end
end

यह मुझे अतिरिक्त तत्वों का निर्माण किए बिना, केवल एक वर्ग का नाम उपयुक्त टैग में जोड़ने की अनुमति देता है।


2
यह विनीत तरीके से त्रुटि क्षेत्रों का उपयोग करने के लिए बहुत बढ़िया है।
रियान

1
पटरियों पर काम करता है 4.0.3।
युकी मत्सुखुरा

1
मेरे लिए काम किया। परिवर्तन को नोटिस करने के लिए रेल सर्वर को पुनः आरंभ करना पड़ा हालांकि :)
Jezen थॉमस

1
मुझे यह समाधान अच्छा लगा, लेकिन अगर आपके अंदर अन्य टैग हैं तो यह काम नहीं करेगा label
कैयो टरीफा

हाय @Phobetron, वास्तव में यह एक अच्छा समाधान है। मैं यहाँ वर्णित के बजाय मूल स्तर पर उस वर्ग को जोड़ने का एक तरीका खोजता हूँ । मैं रेल कोड में कबूतर हूँ, लेकिन मैं अपने आप को तुरंत खो दिया बाईबग के साथ प्रतिपादन प्रक्रिया का पालन करने में सक्षम नहीं किया जा रहा है .. क्या आप यह वास्तव में संभव है?
SanjiBukai

20

द्वारा अतिरिक्त कोड जोड़ा जा रहा है ActionView::Base.field_error_proc। यदि आप field_with_errorsअपने फ़ॉर्म को स्टाइल करने के लिए उपयोग नहीं कर रहे हैं , तो आप इसे ओवरराइड कर सकते हैं application.rb:

config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag.html_safe }

वैकल्पिक रूप से, आप इसे अपने UI पर सूट करने वाली चीज़ में बदल सकते हैं:

config.action_view.field_error_proc = Proc.new { |html_tag, instance| "<span class='field_with_errors'>#{html_tag}</span>".html_safe }

यह मेरे लिए अच्छा काम कर रहा है; ट्विटर बूटस्ट्रैप के साथ उपयोग के लिए सबसे सुरुचिपूर्ण समाधान लगता है
अवीशाई

5

मैं रेल्स 5 और मेटेरियलाइज़-सैस के साथ काम कर रहा हूँ और मुझे रेल्स से डिफ़ॉल्ट व्यवहार के साथ कुछ मुद्दे मिल रहे हैं ताकि नीचे की छवि के रूप में विफल फ़ील्ड मान्यताओं का इलाज किया जा सके और यह divइनपुट फ़ील्ड्स में अतिरिक्त जोड़े जाने के कारण था जहाँ सत्यापन विफल हो गया था।

यहाँ छवि विवरण दर्ज करें

@Pobetron उत्तर के साथ काम करना और ह्यूगो डेमिग्लियो के उत्तर को भी संशोधित करना। मैंने कोड के उन ब्लॉकों में कुछ समायोजन किया है और मुझे निम्नलिखित मामलों में अच्छी तरह से काम करना है:

  • यदि दोनों inputऔर कहीं भी labelअपनी classविशेषता है
    • <input type="my-field" class="control">
    • <label class="active" for="...">My field</label>
  • यदि inputया labelटैग में classविशेषता नहीं है
    • <input type="my-field">
    • <label for="...">My field</label>
  • अगर labelटैग के साथ एक और टैग अंदर हैclass attribute
    • <label for="..."><i class="icon-name"></i>My field</label>

उन सभी मामलों में errorवर्ग को मौजूदा कक्षाओं में classविशेषता में जोड़ा जाएगा यदि मौजूद हैं या यह तब बनाया जाएगा जब यह लेबल या इनपुट टैग में मौजूद नहीं है ।

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
    class_attr_index = html_tag.index('class="')
    first_tag_end_index = html_tag.index('>')

    # Just to inspect variables in the console
    puts '😎 ' * 50
    pp(html_tag)
    pp(class_attr_index)
    pp(first_tag_end_index)

    if class_attr_index.nil? || class_attr_index > first_tag_end_index
        html_tag.insert(first_tag_end_index, ' class="error"')
    else
        html_tag.insert(class_attr_index + 7, 'error ')
    end

    # Just to see resulting tag in the console
    pp(html_tag)
end

मुझे उम्मीद है कि यह मेरे जैसी परिस्थितियों वाले किसी व्यक्ति के लिए उपयोगी हो सकता है।


4

@Phobetron उत्तर के अलावा, जो तब काम नहीं करता जब आपके पास वर्ग विशेषता के साथ अन्य टैग हों, जैसे <label for="..."><i class="icon my-icon"></i>My field</label>

मैंने उसके समाधान पर कुछ बदलाव किए:

# config/initializers/field_with_error.rb

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  class_attr_index = html_tag.index('class="')
  first_tag_end_index = html_tag.index('>')

  if class_attr_index.nil? || first_tag_end_index > class_attr_index
    html_tag.insert(class_attr_index + 7, 'error ')
  else
    html_tag.insert(first_tag_end_index, ' class="error"')
  end
end

लेकिन यह काम नहीं करेगा यदि आपके क्षेत्र में एक क्लास विशेषता नहीं है
mizurnix

2

यदि किसी कारण से आप अभी भी रेल 2 (जैसे मैं हूं) पर काम कर रहे हैं, तो यहां एसओ पद देखें ।

यह इनिशियलाइज़र में डालने के लिए एक स्क्रिप्ट प्रदान करता है।


2

ध्यान रखने वाली एक बात (जैसा कि मैंने आज इसके माध्यम से काम करने का पता लगाया) यह है कि यदि आप या तो लेबल या इनपुट फ़ील्ड (मैं इनपुट क्षेत्रों के सभी सही चल रहा हूं) को तैरता हूं, तो सीएसएस टूट जाएगा भले ही आप एक्शन व्यू को ओवरराइड कर दें :: Base.field_error_proc।

एक विकल्प सीएसएस स्वरूपण में एक स्तर को गहरा छोड़ने के लिए है:

.field_with_errors label {
  padding: 2px;
  background-color: red;
}

.field_with_errors input[type="text"] {
  padding: 3px 2px;
  border: 2px solid red;
}

2

मैंने कुछ वस्तुओं के लिए इस भयानक चीज़ को निष्क्रिय करने का विकल्प बनाया

# config/initializers/field_error_proc.rb

module ActiveModel::Conversion
  attr_accessor :skip_field_error_wrapper
end

ActionView::Base.field_error_proc = Proc.new {|html_tag, instance|
  if instance.object && instance.object.skip_field_error_wrapper
    html_tag.html_safe
  else
    "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
  end
}

तो इसे इस तरह से उपयोग कर सकते हैं:

@user.skip_field_error_wrapper = true
form_for(@user) do |f|
  ...
end

1

यह मेरे Phobetron के उत्तर के शीर्ष पर मेरी समाधान इमारत है। इस कोड को रखने से, संबंधित कॉल द्वारा उत्पन्न application.rbआपके <p>और <span>टैग form.error :pको fields_with_errorsसीएसएस टैग प्राप्त होगा । बाकी errorसीएसएस वर्ग प्राप्त करेंगे ।

config.action_view.field_error_proc = Proc.new { |html_tag, instance|
  class_attr_index = html_tag.index 'class="'

  if class_attr_index
    # target only p's and span's with class error already there
    error_class = if html_tag =~ /^<(p|span).*error/
      'field_with_errors '
    else
      'error '
    end

    html_tag.insert class_attr_index + 7, error_class
  else
    html_tag.insert html_tag.index('>'), ' class="error"'
  end
}

मैंने इस तरह से अपने सभी रूपों में प्रतिक्रिया को स्टाइल करने के लिए पिछले सभी के सबसे अधिक लचीले और अप्रतिष्ठित पाया।


1

यदि यह सिर्फ स्टाइलिंग के उद्देश्य (आप बुरा न मानें div) के लिए है, तो आप इसे अपने css में जोड़ सकते हैं:

div.field_with_errors {
 display: inline;
}

divएक तरह कार्य करेगा spanऔर इसे अपने डिजाइन के साथ हस्तक्षेप नहीं करेगा (के बाद से divएक ब्लॉक तत्व है - display: block;- डिफ़ॉल्ट रूप से, यह एक नई लाइन यह बंद कर देता है के बाद का कारण होगा; spanहै inline, इसलिए यह नहीं है)।


1

यदि आप कुछ तत्वों जैसे उदाहरण चेकबॉक्स के लिए त्रुटियों को बंद करना चाहते हैं , तो आप ऐसा कर सकते हैं:

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  doc = Nokogiri::HTML::Document.parse(html_tag)
  if doc.xpath("//*[@type='checkbox']").any?
    html_tag
  else
    "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
  end
end

0

यदि इसके केवल स्टाइलिंग मुद्दों के बारे में है, तो हम "field_with_errors" को ओवरराइट कर सकते हैं। लेकिन जैसा कि हमारे आवेदन में अन्य रूपों को प्रभावित कर सकता है, केवल उस फॉर्म के साथ "field_with_errors" वर्ग को अधिलेखित करना बेहतर है।

'Parent_class' को फॉर्म के एरर फील्ड के लिए पैरेंट क्लास में से एक माना जाता है (एरर फील्ड के लिए किसी भी पैरेंट एलिमेंट की क्लास या क्लास), तब

  .parent_class .field_with_errors {
    display: inline;
  }

यह समस्या को तो ठीक करेगा ही, साथ ही यह हमारे एप्लीकेटन में किसी भी अन्य रूप को भी परेशान नहीं करेगा।

या

अगर हमें पूरे एप्लिकेशन के लिए "फ़ील्ड_विथ_रियर्स" की शैली को ओवरराइड करने की आवश्यकता है, तो @ डोंटांग ने कहा,

.field_with_errors { display: inline; } 

ठीक कर देंगे। आशा करता हूँ की ये काम करेगा :)


0

यदि आप field_error_procअपने संपूर्ण एप्लिकेशन के लिए परिवर्तन नहीं करना चाहते हैं , तो jQuery का अनट्रैप विशिष्ट समस्या वाले क्षेत्रों के लिए अधिक लक्षित समाधान प्रदान कर सकता है, जैसे;

$('FORM .field_with_errors > INPUT[type="checkbox"]').unwrap();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.