Skip to content

Commit

Permalink
added label_for helper
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Sep 28, 2013
1 parent a253f44 commit b54b82c
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Changes
Expand Up @@ -5,7 +5,7 @@
Mojolicious::Validator::Validation.
- Added EXPERIMENTAL validation method to Mojolicious::Controller.
- Added EXPERIMENTAL validator attribute to Mojolicious.
- Added EXPERIMENTAL validation helper to
- Added EXPERIMENTAL label_for and validation helpers to
Mojolicious::Plugin::DefaultHelpers.

4.41 2013-09-22
Expand Down
15 changes: 12 additions & 3 deletions lib/Mojolicious/Guides/Rendering.pod
Expand Up @@ -647,17 +647,23 @@ you can perform checks on their values.
<html>
<head>
%= stylesheet begin
label.field-with-error { color: #dd7e5e }
input.field-with-error { background-color: #fd9e7e }
% end
</head>
<body>
%= form_for index => begin
<p>Username (required, can only contain the characters e-t)</p>
%= label_for user => 'Username (required, only characters e-t)'
<br>
%= text_field 'user'
%= submit_button
<p>Password (optional, needs to be 7-500 characters long)</p>
<br>
%= label_for pass => 'Password (optional, 7-500 characters long)'
<br>
%= password_field 'pass'
<p>Password again (needs to be equal to the value above)</p>
<br>
%= label_for pass_again => 'Password again (equal to the value above)'
<br>
%= password_field 'pass_again'
% end
</html>
Expand All @@ -672,6 +678,9 @@ L<Mojolicious::Plugin::TagHelpers> will automatically remember their previous
values and add the class C<field-with-error> for fields that failed validation
to make styling with CSS easier.

<label class="field-with-error" for="user">
Username (required, only characters e-t)
</label>
<input class="field-with-error" type="text" name="user" value="sri" />

Every check is performed right away, so you can use the results immediately to
Expand Down
47 changes: 41 additions & 6 deletions lib/Mojolicious/Plugin/TagHelpers.pm
Expand Up @@ -23,10 +23,10 @@ sub register {
$app->helper(image => sub { _tag('img', src => shift->url_for(shift), @_) });
$app->helper(input_tag => sub { _input(@_) });
$app->helper(javascript => \&_javascript);
$app->helper(label_for => \&_label_for);
$app->helper(link_to => \&_link_to);

$app->helper(password_field =>
sub { _validation(shift, shift, 'input', @_, type => 'password') });
$app->helper(password_field => \&_password_field);
$app->helper(radio_button =>
sub { _input(shift, shift, value => shift, @_, type => 'radio') });

Expand Down Expand Up @@ -84,7 +84,7 @@ sub _input {
else { $attrs{value} = $values[0] }
}

return _validation($self, $name, 'input', %attrs);
return _validation($self, $name, 'input', %attrs, name => $name);
}

sub _javascript {
Expand All @@ -103,6 +103,12 @@ sub _javascript {
return _tag('script', @_, $src ? (src => $src) : (), $cb);
}

sub _label_for {
my ($self, $name) = (shift, shift);
my $content = ref $_[-1] eq 'CODE' ? pop : shift;
return _validation($self, $name, 'label', for => $name, @_, $content);
}

sub _link_to {
my ($self, $content) = (shift, shift);
my @url = ($content);
Expand All @@ -119,6 +125,12 @@ sub _link_to {
return _tag('a', href => $self->url_for(@url), @_);
}

sub _password_field {
my ($self, $name) = (shift, shift);
return _validation($self, $name, 'input', @_, name => $name,
type => 'password');
}

sub _select_field {
my ($self, $name, $options, %attrs) = (shift, shift, shift, @_);

Expand Down Expand Up @@ -159,7 +171,7 @@ sub _select_field {
return $parts;
};

return _validation($self, $name, 'select', %attrs, $optgroup);
return _validation($self, $name, 'select', %attrs, name => $name, $optgroup);
}

sub _stylesheet {
Expand Down Expand Up @@ -224,15 +236,15 @@ sub _text_area {
$cb = sub { xml_escape $content }
}

return _validation($self, $name, 'textarea', @_, $cb);
return _validation($self, $name, 'textarea', @_, name => $name, $cb);
}

sub _validation {
my ($self, $name, $tag) = (shift, shift, shift);
my ($content, %attrs) = (@_ % 2 ? pop : undef, @_);
$attrs{class} .= $attrs{class} ? ' field-with-error' : 'field-with-error'
if $self->validation->has_error($name);
return _tag($tag, name => $name, %attrs, $content ? $content : ());
return _tag($tag, %attrs, $content ? $content : ());
}

1;
Expand Down Expand Up @@ -432,6 +444,29 @@ Generate portable script tag for C<Javascript> asset.
var a = 'b';
]]></script>
=head2 label_for
%= label_for first_name => 'First name'
%= label_for first_name => 'First name, class => 'labels'
%= label_for first_name => begin
First name
% end
%= label_for first_name => (class => 'labels') => begin
First name
% end
Generate label. Note that this helper is EXPERIMENTAL and might change without
warning!
<label for="first_name">First name</label>
<label class="labels" for="first_name">First name</label>
<label for="first_name">
First name
</label>
<label class="labels" for="first_name">
First name
</label>
=head2 link_to
%= link_to Home => 'index'
Expand Down
2 changes: 2 additions & 0 deletions t/mojolicious/tag_helper_lite_app.t
Expand Up @@ -115,6 +115,7 @@ EOF
# Basic form
$t->get_ok('/basicform')->status_is(200)->content_is(<<EOF);
<form action="/links">
<label for="foo">&lt;Foo&gt;</label>
<input name="foo" type="text" value="bar" />
<input class="test" name="bar" type="text" value="baz" />
<input name="yada" type="text" value="" />
Expand Down Expand Up @@ -468,6 +469,7 @@ __DATA__
@@ basicform.html.ep
%= form_for links => begin
%= label_for foo => '<Foo>'
%= text_field foo => 'bar'
%= text_field bar => 'baz', class => 'test'
%= text_field yada => undef
Expand Down
22 changes: 16 additions & 6 deletions t/mojolicious/validation_lite_app.t
Expand Up @@ -139,21 +139,27 @@ ok $validation->has_error('bar'), 'has error';

# No validation
$t->get_ok('/')->status_is(200)->element_exists_not('div:root')
->text_is('label[for="foo"]' => '<Foo>')
->element_exists('input[type="text"]')->element_exists('textarea')
->element_exists('select')->element_exists('input[type="password"]');
->text_is('label[for="baz"]' => 'Baz')->element_exists('select')
->element_exists('input[type="password"]');

# Successful validation
$t->get_ok('/?foo=ok')->status_is(200)->element_exists_not('div:root')
->text_is('label[for="foo"]' => '<Foo>')
->element_exists('input[type="password"]')->element_exists('textarea')
->element_exists('select')->element_exists('input[type="password"]');
->text_is('label[for="baz"]' => 'Baz')->element_exists('select')
->element_exists('input[type="password"]');

# Failed validation
$t->get_ok('/?foo=too_long&bar=too_long_too&baz=way_too_long&yada=whatever')
->status_is(200)->text_is('div:root' => 'My error.')
->element_exists('input[type="text"][class="custom field-with-error"]')
->element_exists('textarea[class="field-with-error"]')
->element_exists('select[class="field-with-error"]')
->element_exists('input[type="password"][class="field-with-error"]');
->text_is('label.custom.field-with-error[for="foo"]' => '<Foo>')
->element_exists('input.custom.field-with-error[type="text"]')
->element_exists('textarea.field-with-error')
->text_is('label.custom.field-with-error[for="baz"]' => 'Baz')
->element_exists('select.field-with-error')
->element_exists('input.field-with-error[type="password"]');

done_testing();

Expand All @@ -164,8 +170,12 @@ __DATA__
<div><%= validation->errors('foo') %></div>
% }
%= form_for index => begin
%= label_for foo => '<Foo>', class => 'custom'
%= text_field 'foo', class => 'custom'
%= text_area 'bar'
%= label_for baz => (class => 'custom') => begin
Baz
% end
%= select_field baz => [qw(yada yada)]
%= password_field 'yada'
% end

0 comments on commit b54b82c

Please sign in to comment.