Forum: Ruby on Rails TIP: Using field_error_proc to add style attributes to form

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Duane J. (Guest)
on 2006-01-19 23:02
(Received via mailing list)
I just put this up on the wiki, and thought I'd share in case it's
useful to anyone else.  This is handy if you donĂ¢??t want to wrap your
input elements inside a div when an error occurs, but instead want to
add some sort of CSS style to fields with errors:

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
   msg = instance.error_message
   error_style = "background-color: #f2afaf"
   if html_tag =~ /<(input|textarea|select)[^>]+style=/
     style_attribute = html_tag =~ /style=['"]/
     html_tag.insert(style_attribute + 7, "#{error_style}; ")
   elsif html_tag =~ /<(input|textarea|select)/
     first_whitespace = html_tag =~ /\s/
     html_tag[first_whitespace] = " style='#{error_style}' "
   end
   html_tag
end

(wrapping fields in a div always seems to mess my layout up a bit)

From: http://wiki.rubyonrails.com/rails/pages/
HowtoChangeValidationErrorDisplay

Duane J.
(canadaduane)
http://blog.inquirylabs.com/
Ian H. (Guest)
on 2006-01-20 03:39
(Received via mailing list)
On 1/19/06, Duane J. <removed_email_address@domain.invalid> wrote:
>     html_tag.insert(style_attribute + 7, "#{error_style}; ")
> http://wiki.rubyonrails.com/rails/pages/HowtoChang...
>
>

Looks interesting.  My first Rails program involves a "multiple child
record update" scenario, rendering a collection of partials and using
the :index attribute of the resulting params array. (I hope my
OO/Rails lingo is close...)  Anyway, is there any way to get this kind
of error identification by the offending input widget working in that
scenario?  It's been automatic when updating a single record.

Thanks!

- Ian
Duane J. (Guest)
on 2006-01-21 00:47
(Received via mailing list)
On Jan 19, 2006, at 6:00 PM, Ian H. wrote:

>>   msg = instance.error_message
>>
> the :index attribute of the resulting params array. (I hope my
> OO/Rails lingo is close...)  Anyway, is there any way to get this kind
> of error identification by the offending input widget working in that
> scenario?  It's been automatic when updating a single record.
>
> Thanks!
>
There's a super-secret and mostly undocumented way of doing this
that's kind of handy, actually.  It looks like this:

<% for @comment in @post.comments %>
<%= text_field 'comment[]', 'author' %>
<%= text_field 'comment[]', 'body' %>
<% end %>

The FormTagHelper will pick up the square brackets and realize you
want the index of the object in there, producing HTML like this:

<input type="text" name="comment[42][author]" id="comment_42_author"
value="Duane">
<input type="text" name="comment[42][body]" id="comment_42_body"
value="I think your site is great...">

It's important that you assign a class variable in the loop (i.e.
"@comment" not "comment" in the for loop above).  If that's all set
up correctly, then you should be able to get the same automagic error
identification results as you do for normal (single) fields.



Duane J.
(canadaduane)
http://blog.inquirylabs.com/
Duane J. (Guest)
on 2006-01-21 00:53
(Received via mailing list)
On Jan 19, 2006, at 6:00 PM, Ian H. wrote:

>>   msg = instance.error_message
>>
> the :index attribute of the resulting params array. (I hope my
> OO/Rails lingo is close...)  Anyway, is there any way to get this kind
> of error identification by the offending input widget working in that
> scenario?  It's been automatic when updating a single record.
>
> Thanks!
>
> - Ian

Oh, it just occurred to me what you're asking.  :)

You'll need to call the "valid?" method on each object in the array
so that the validation code can be run, and thus, any errors that
should show up will.

For example, in your controller:

all_valid = @post.comments.all? { |c| c.valid? }

The above line has the effect of both adding error messages to each
objects internal error array, and returning 'true' or 'false'
depending on whether or not all comments are valid.


Duane J.
(canadaduane)
http://blog.inquirylabs.com/
Ian H. (Guest)
on 2006-01-21 01:02
(Received via mailing list)
Hmm.  Ok, I have been doing

<%= text_field 'comment','author', :index => comment_counter %>

or something like that, but that uses a local variable as handed over
in the render call.  I need to look and see but I guess I was not
instantiating a class variable.

The other sticky wicket is the ajax autocomplete stuff.  It works
wonderfully with the basic single record update/insert where there is
no index.  I assume I will have to open the hood on the ajax stuff to
make it work in the context of a form with an arbitrary number of
indexed records on it.

Thank you so much for taking the time to respond!

- Ian

On 1/20/06, Duane J. <removed_email_address@domain.invalid> wrote:
> >> style to fields with errors:
> >>   end
> >
> that's kind of handy, actually.  It looks like this:
> value="Duane">
> Duane J.
> (canadaduane)
> http://blog.inquirylabs.com/
>
>
>


--
"Her faults were those of her race and sex; her virtues were her own.
Farewell, and if for ever - "

-- "Travels with a Donkey in the Cevennes" by Robert Louis Stevenson
Francois B. (Guest)
on 2006-01-21 03:33
(Received via mailing list)
Hi !

2006/1/20, Duane J. <removed_email_address@domain.invalid>:
> all_valid = @post.comments.all? { |c| c.valid? }

Sorry Duane, but that won't work if one instance is invalid.
Enumerable#all? short-circuits evaluation when it can, so c.valid?
might not run on the last entries in the array.

A better way, I think, would be:

all_valid = @post.comments.inject(true) {|memo, c| c.valid? && memo }

c.valid? will be evaluated for all instances, and all_valid will be
true/false, as in the initial example.

I hope I'm not making a mistake in full view of the public :)

Bye !
This topic is locked and can not be replied to.