2009-06-21 2 views
1

Я хотел бы иметь возможность генерировать следующую разметку:Создания настраиваемых полей меток в формах

<label for="field">Something <span class="hint">Field hint</span></label> 

из следующего кода:

form_for ... do |f| 
    f.label :field, :hint => "Field hint" 
end 

До сих пор я создал инициализатор для сохраните пользовательские функции, которые вновь открывают ActionView :: Helpers :: FormBuilder и меняют метод меток, однако я не уверен, что лучший способ фактически получить интервал в тексте для метки. Если я попытаюсь поместить текст непосредственно, тогда рельсы, правильно, избегают содержимого.

Мне очень хотелось бы использовать существующую инфраструктуру ярлыков, поскольку она имеет всю поддержку ошибок проверки. Это исключает использование content_tag и генерирует все это самостоятельно (что будет работать, но не кажется ... правильным).

ответ

3

Вместо изменения конструктора по умолчанию вы должны создать собственный конструктор и передать его в форму с параметром: builder.

class HintFormBuilder < ActionView::Helpers::FormBuilder 
end 

form_for @resource, :builder => HintFormBuilder do |f| 
# ... 
end 

Конструктор Hint наследует все функции FormBuilder, включая проверки, сообщения об ошибках и т. Д. Теперь вы должны изменить то, что вам нужно изменить, чтобы настроить поведение. Это действительно сырой проект.

class HintFormBuilder < ActionView::Helpers::FormBuilder 

    (%w(label)).each do |selector| 
    src = <<-end_src 
     def #{selector}(method, options = {}) 
     hint = options.delete(:hint) 
     returning(super) do |element| 
      # replace here the value of element with hint 
      # if hint != nil 
      # remember to use gsub! and not gsub 
     end 
     end 
    end_src 
    class_eval src, __FILE__, __LINE__ 
    end 

end 

EDIT на основе первого комментария:

Это всегда хорошая идея, чтобы не взломать внутренние Rails, потому что вы, возможно, придется использовать, в настоящее время или в будущем, плагины или функции, которые полагаются на оригинальное поведение. Если вы не хотите вручную добавлять строитель в свои формы, вы можете создать помощника.

Защиту search_form_for (record_or_name_or_array, * Args, & прок) опции = {: строитель => HintFormBuilder}

form_for(record_or_name_or_array, 
     *(args << options), 
     &proc) 

конец

Если вы хотите, чтобы вновь открыть исходный класс вместо этого, я хотел бы предложить для создания нового метода. Это решение также относится к пользовательскому помощнику и имеет преимущество, которое вы можете настроить без необходимости gsub! ответ. Да, gsub! это обычный способ сделать это, потому что при расширении исходных методов у вас есть только доступ к методу/параметрам и результату, нет значения (которое вводится переменной @object).

class ActionView::Helpers::FormBuilder 

    def label_with_hint(method, text = nil, options = {}) 
    hint = options.delete(:hint) 
    # do your own customizations... 
    @template.label(@object_name, method, text, objectify_options(options)) 
    end 

end 

EDIT: я ошибся, вы можете передать свой текст в качестве параметра, поэтому вам не нужно GSUB! возвращенная строка. Я смутился тегом text_field. На этом этапе вы можете использовать либо первый (подклассы с/без пользовательского метода), второй (внутренние хаки), либо третий вариант (хакинг внутри с настраиваемым методом) и перехват текстового значения до его отправки в @ template.label.

Также обратите внимание, что текст может быть равен нулю. Если nil, значение автоматически генерируется из метода. Вы должны знать об этом.

+0

Я действительно не хочу указывать конструктор форм, который я хочу использовать для каждой формы. Кроме того, я уверен, что должен быть лучший способ, чем gsub-ing в значении ... – jonnii

+0

Я не знаю, почему кто-то проголосовал за это сообщение. – jonnii

1

Вот что я сделал бы.

# config/initializers/[anything].rb 
ActionView::Base.default_form_builder = CustomFormBuilder 

# lib/custom_form_builder.rb 
class CustomFormBuilder < ActionView::Helpers::FormBuilder 
    def label(field, text, options = {}) 
    if options[:hint] 
     hint = @template.content_tag(:span, options[:hint], :class => "hint") 
     super(field, "#{field.to_s.humanize} #{hint}", options) 
    else 
     super 
    end 
    end 
end 
+0

Я не знал, что вы можете установить построитель форм по умолчанию, это действительно полезная функция. Вы пробовали этот подход? Я думаю, что он страдает от той же проблемы, с которой я столкнулся, что супер метод html кодирует текст. – jonnii

Смежные вопросы