changes so far for new moose / mop
[catagits/Reaction.git] / lib / Reaction / UI / ViewPort / Field.pm
CommitLineData
7adfd53f 1package Reaction::UI::ViewPort::Field;
2
3use Reaction::Class;
4
5class Field is 'Reaction::UI::ViewPort', which {
6
7 has name => (
8 isa => 'Str', is => 'rw', required => 1
9 );
10
11 has action => (
12 isa => 'Reaction::InterfaceModel::Action',
13 is => 'ro', required => 0, predicate => 'has_action',
14 );
15
16 has attribute => (
17 isa => 'Reaction::Meta::InterfaceModel::Action::ParameterAttribute',
18 is => 'ro', predicate => 'has_attribute',
19 );
20
21 has value => (
22 is => 'rw', lazy_build => 1, trigger_adopt('value'),
23 clearer => 'clear_value',
24 );
25
26 has needs_sync => (
27 isa => 'Int', is => 'rw', default => 0
28 );
29
30 has label => (isa => 'Str', is => 'rw', lazy_build => 1);
31
32 has message => (
33 isa => 'Str', is => 'rw', required => 1, default => sub { '' }
34 );
35
36 implements BUILD => as {
37 my ($self) = @_;
38 if (!$self->has_attribute != !$self->has_action) {
39 confess "Should have both action and attribute or neither";
40 }
41 };
42
89939ff9 43 implements _build_label => as {
7adfd53f 44 my ($self) = @_;
6ab43711 45 my $label = join(' ', map { ucfirst } split('_', $self->name));
de48f4e6 46 # print STDERR "Field " . $self->name . " has label '$label'\n";
6ab43711 47 return $label;
7adfd53f 48 };
49
89939ff9 50 implements _build_value => as {
7adfd53f 51 my ($self) = @_;
52 if ($self->has_attribute) {
53 my $reader = $self->attribute->get_read_method;
54 my $predicate = $self->attribute->predicate;
55 if (!$predicate || $self->action->$predicate) {
56 return $self->action->$reader;
57 }
58 }
59 return '';
60 };
61
62 implements adopt_value => as {
63 my ($self) = @_;
64 $self->needs_sync(1) if $self->has_attribute;
65 };
66
67 implements sync_to_action => as {
68 my ($self) = @_;
69 return unless $self->needs_sync && $self->has_attribute && $self->has_value;
70 my $attr = $self->attribute;
71 if (my $tc = $attr->type_constraint) {
72 my $value = $self->value;
73 if ($tc->has_coercion) {
74 $value = $tc->coercion->coerce($value);
75 }
76 my $error = $tc->validate($self->value);
77 if (defined $error) {
78 $self->message($error);
79 return;
80 }
81 }
82 my $writer = $attr->get_write_method;
83 confess "No writer for attribute" unless defined($writer);
84 $self->action->$writer($self->value);
85 $self->needs_sync(0);
86 };
87
88 implements sync_from_action => as {
89 my ($self) = @_;
90 return unless !$self->needs_sync && $self->has_attribute;
91 $self->message($self->action->error_for($self->attribute)||'');
92 };
93
94 override accept_events => sub { ('value', super()) };
95
96};
97
981;
99
100=head1 NAME
101
102Reaction::UI::ViewPort::Field
103
104=head1 DESCRIPTION
105
106This viewport is the base class for all field types.
107
108=head1 ATTRIBUTES
109
110=head2 name
111
112=head2 action
113
114L<Reaction::InterfaceModel::Action>
115
116=head2 attribute
117
118L<Reaction::Meta::InterfaceModel::Action::ParameterAttribute>
119
120=head2 value
121
122=head2 needs_sync
123
124=head2 label
125
126User friendly label, by default is based on the name.
127
128=head2 message
129
130Optional string relating to the field.
131
132=head1 SEE ALSO
133
134=head2 L<Reaction::UI::ViewPort>
135
136=head2 L<Reaction::UI::ViewPort::DisplayField>
137
138=head2 L<Reaction::UI::ViewPort::Field::Boolean>
139
140=head2 L<Reaction::UI::ViewPort::Field::ChooseMany>
141
142=head2 L<Reaction::UI::ViewPort::Field::ChooseOne>
143
144=head2 L<Reaction::UI::ViewPort::Field::DateTime>
145
146=head2 L<Reaction::UI::ViewPort::Field::File>
147
148=head2 L<Reaction::UI::ViewPort::Field::HiddenArray>
149
150=head2 L<Reaction::UI::ViewPort::Field::Number>
151
152=head2 L<Reaction::UI::ViewPort::Field::Password>
153
154=head2 L<Reaction::UI::ViewPort::Field::String>
155
156=head2 L<Reaction::UI::ViewPort::Field::Text>
157
158=head2 L<Reaction::UI::ViewPort::Field::TimeRange>
159
160=head1 AUTHORS
161
162See L<Reaction::Class> for authors.
163
164=head1 LICENSE
165
166See L<Reaction::Class> for the license.
167
168=cut