Index: lib/HTML/Widget/Constraint/Any.pm
===================================================================
--- lib/HTML/Widget/Constraint/Any.pm	(revision 5057)
+++ lib/HTML/Widget/Constraint/Any.pm	(working copy)
@@ -4,6 +4,8 @@
 use strict;
 use base 'HTML::Widget::Constraint';
 
+__PACKAGE__->mk_accessors(qw/display_errors/);
+
 =head1 NAME
 
 HTML::Widget::Constraint::Any - Any Constraint
@@ -18,6 +20,13 @@
 
 =head1 METHODS
 
+=head2 display_errors
+
+Arguments: @names
+
+The names of fields in this constraint which will have errors attached to 
+them if none of the fields are present.  Optional, defaults to all.
+
 =head2 process
 
 =cut
@@ -27,12 +36,18 @@
 
     my $results = [];
     my $present = 0;
+
+	my @display_names = $self->display_errors || @{ $self->names };
+	@display_names = @{$display_names[0]} if ref $display_names[0];
+
     for my $name ( @{ $self->names } ) {
-        unless ( $params->{$name} ) {
+        if ( $params->{$name} ) {
+			$present++ 
+        } else { 
             push @$results, HTML::Widget::Error->new(
-                { name => $name, message => $self->mk_message } );
-        }
-        else { $present++ }
+                { name => $name, message => $self->mk_message } )
+				if grep { $_ eq $name } @display_names;
+		}
     }
     $present = $self->not ? !$present : $present;
     return $present ? [] : $results;
Index: lib/HTML/Widget/Constraint/CallbackOnce.pm
===================================================================
--- lib/HTML/Widget/Constraint/CallbackOnce.pm	(revision 5057)
+++ lib/HTML/Widget/Constraint/CallbackOnce.pm	(working copy)
@@ -4,7 +4,7 @@
 use strict;
 use base 'HTML::Widget::Constraint';
 
-__PACKAGE__->mk_accessors(qw/callback/);
+__PACKAGE__->mk_accessors(qw/callback display_errors/);
 
 *cb = \&callback;
 
@@ -38,6 +38,13 @@
 
 L</cb> is provided as an alias to L</callback>.
 
+=head2 display_errors
+
+Arguments: @names
+
+The names of fields in this constraint which will have errors attached to 
+them.  Optional, defaults to all.
+
 =head2 process
 
 Overrides L<HTML::Widget::Constraint/"process"> to ensure L</validate> is 
@@ -55,8 +62,11 @@
 
     my $results = [];
 
+	my @display_names = $self->display_errors || @names;
+	@display_names = @{$display_names[0]} if ref $display_names[0];
+
     if ( $self->not ? $result : !$result ) {
-        for my $name (@names) {
+        for my $name (@display_names) {
             push @$results, HTML::Widget::Error->new(
                 { name => $name, message => $self->mk_message } );
         }
Index: lib/HTML/Widget/Constraint/Equal.pm
===================================================================
--- lib/HTML/Widget/Constraint/Equal.pm	(revision 5057)
+++ lib/HTML/Widget/Constraint/Equal.pm	(working copy)
@@ -4,6 +4,8 @@
 use strict;
 use base 'HTML::Widget::Constraint';
 
+__PACKAGE__->mk_accessors(qw/display_errors/);
+
 =head1 NAME
 
 HTML::Widget::Constraint::Equal - Equal Constraint
@@ -17,8 +19,18 @@
 Equal Constraint. All provided elements must be the same. Combine this
 with the All constraint to make sure all elements are equal.
 
+If this constraint fails, all elements have an error set for them, unless
+display_errors is set.
+
 =head1 METHODS
 
+=head2 display_errors
+
+Arguments: @names
+
+The names of fields in this constraint which will have errors attached to 
+them if any of the fields are not equal.  Optional, defaults to all.
+
 =head2 process
 
 =cut
@@ -27,13 +39,24 @@
     my ( $self, $w, $params ) = @_;
     my $results = [];
     my $equal   = $params->{ ${ $self->names }[0] };
-    for my $name ( @{ $self->names } ) {
-        push @$results,
-            HTML::Widget::Error->new(
-            { name => $name, message => $self->mk_message } )
-            if $params->{$name} ne $equal;
+	my $failures = 0;
+
+	for my $name ( @{ $self->names } ) {
+		$failures++ if $params->{$name} ne $equal;
     }
-    return $results;
+
+	my @display_names = $self->display_errors || @{ $self->names };
+	@display_names = @{$display_names[0]} if ref $display_names[0];
+	
+	if ($failures) {
+		for my $name (@display_names) {
+			push @$results,
+				HTML::Widget::Error->new(
+				{ name => $name, message => $self->mk_message } );
+		}
+	}
+
+	return $results;
 }
 
 =head1 AUTHOR
Index: t/constraint_any.t
===================================================================
--- t/constraint_any.t	(revision 5057)
+++ t/constraint_any.t	(working copy)
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 4;
+use Test::More tests => 8;
 
 use HTML::Widget;
 use lib 't/lib';
@@ -12,7 +12,7 @@
 $w->element( 'Textfield', 'foo' );
 $w->element( 'Textfield', 'bar' );
 
-$w->constraint( 'Any', 'foo', 'bar' );
+my $constraint = $w->constraint( 'Any', 'foo', 'bar' );
 
 # Valid
 {
@@ -34,3 +34,25 @@
     ok( $f->errors('foo'), 'foo has errors' );
     ok( $f->errors('bar'), 'bar has errors' );
 }
+
+# Multiple invalid, error only on one
+{
+	$constraint->display_errors(qw/ foo /);
+    my $query = HTMLWidget::TestLib->mock_query( { baz => 23 } );
+
+    my $f = $w->process($query);
+
+    ok( $f->errors('foo'), 'foo has errors' );
+    ok( !$f->errors('bar'), 'bar does not show error' );
+}
+
+# Multiple invalid, error on both (explicitly)
+{
+	$constraint->display_errors(qw/ foo bar /);
+    my $query = HTMLWidget::TestLib->mock_query( { baz => 23 } );
+
+    my $f = $w->process($query);
+
+    ok( $f->errors('foo'), 'foo has errors' );
+    ok( $f->errors('bar'), 'bar has errors' );
+}
\ No newline at end of file
Index: t/constraint_callbackonce.t
===================================================================
--- t/constraint_callbackonce.t	(revision 5057)
+++ t/constraint_callbackonce.t	(working copy)
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 15;
+use Test::More tests => 21;
 
 use HTML::Widget;
 use lib 't/lib';
@@ -13,7 +13,7 @@
 $w->element( 'Textfield', 'foo' );
 $w->element( 'Textfield', 'bar' );
 
-$w->constraint( 'CallbackOnce', 'foo', 'bar' )
+my $constraint = $w->constraint( 'CallbackOnce', 'foo', 'bar' )
     ->callback( sub { $counter++; return 1 if $_[0] && $_[1] } );
 
 # Valid
@@ -86,3 +86,33 @@
 
     is( $counter, 1 );
 }
+
+# Display one error on multiple failure
+{
+	$constraint->display_errors(qw/ foo /);
+    my $query = HTMLWidget::TestLib->mock_query( { foo => [ '', '' ] } );
+
+    local $counter = 0;
+
+    my $f = $w->process($query);
+
+    ok( $f->errors('foo'), 'foo has errors' );
+    ok( !$f->errors('bar'), 'bar does not show error' );
+
+    is( $counter, 1 );
+}
+
+# Display both errors (explicitly) on multiple failure
+{
+	$constraint->display_errors(qw/ foo bar /);
+    my $query = HTMLWidget::TestLib->mock_query( { foo => [ '', '' ] } );
+
+    local $counter = 0;
+
+    my $f = $w->process($query);
+
+    ok( $f->errors('foo'), 'foo has errors' );
+    ok( $f->errors('bar'), 'bar has errors' );
+
+    is( $counter, 1 );
+}
Index: t/constraint_equal.t
===================================================================
--- t/constraint_equal.t	(revision 5057)
+++ t/constraint_equal.t	(working copy)
@@ -12,13 +12,14 @@
 $w->element( 'Textfield', 'foo' );
 $w->element( 'Textfield', 'bar' );
 
-$w->constraint( 'Equal', 'foo', 'bar' );
+my $constraint = $w->constraint( 'Equal', 'foo', 'bar', 'baz' );
 
 # Valid
 {
     my $query = HTMLWidget::TestLib->mock_query( {
             foo => 'yada',
             bar => 'yada',
+			baz => 'yada',
         } );
 
     my $f = $w->process($query);
@@ -36,6 +37,7 @@
     my $query = HTMLWidget::TestLib->mock_query( {
             foo => '',
             bar => 'yada',
+			baz => 'yada',
         } );
 
     my $f = $w->process($query);
@@ -50,6 +52,7 @@
     my $query = HTMLWidget::TestLib->mock_query( {
             foo => 'yada',
             bar => '',
+			baz => 'yada',
         } );
 
     my $f = $w->process($query);
@@ -61,15 +64,65 @@
 # Invalid
 {
     my $query = HTMLWidget::TestLib->mock_query( {
+            'foo' => 'yada',
+            'bar' => 'nada',
+			'baz' => 'yada',
+        } );
+
+    my $f = $w->process($query);
+
+    ok(!$f->param('foo'), 'param foo is undef due to error' );
+    ok(!$f->param('bar'), 'param bar is undef due to error' );
+
+    ok( $f->errors('foo'), 'foo has errors' );
+    ok( $f->errors('bar'), 'bar has errors' );
+}
+
+# Display error on first value only
+{
+	$constraint->display_errors(qw/ foo /);
+    my $query = HTMLWidget::TestLib->mock_query( {
             foo   => 'yada',
             'bar' => 'nada',
+			'baz' => 'nada',
         } );
 
     my $f = $w->process($query);
 
-    is( $f->param('foo'), 'yada', 'foo value' );
+    ok( $f->errors('foo'), 'foo shows error' );
+	ok(!$f->errors('bar'), 'bar does not show error' );
+	ok(!$f->errors('baz'), 'baz does not show error' );
+}
 
-    isnt( $f->param('foo'), $f->param('bar'), 'foo ne bar' );
+# Display error on some
+{
+	$constraint->display_errors(qw/ foo bar /);
+    my $query = HTMLWidget::TestLib->mock_query( {
+            foo   => 'yada',
+            'bar' => 'nada',
+			'baz' => 'something completely different',
+        } );
 
-    ok( $f->errors('bar'), 'bar has errors' );
+    my $f = $w->process($query);
+
+    ok( $f->errors('foo'), 'foo shows error' );
+	ok( $f->errors('bar'), 'bar shows error too' );
+	ok(!$f->errors('baz'), 'baz does not get error' );
 }
+
+# Display error on exactly what the user asked for
+{
+	$constraint->display_errors(qw/ baz /);
+    my $query = HTMLWidget::TestLib->mock_query( {
+            foo   => 'yada',
+            'bar' => 'nada',
+			'baz' => 'yada',
+        } );
+
+    my $f = $w->process($query);
+
+    ok(!$f->errors('foo'), 'foo does not get error, even though it should' );
+	ok( $f->errors('bar'), 'bar does not get error, even though it should' );
+	ok( $f->errors('baz'), 'baz gets the error, because that is what the user asked for' );
+}
+
