Bivio::Biz::ExpandableListFormModel
# Copyright (c) 1999-2007 bivio Software, Inc. All rights reserved.
# $Id$
package Bivio::Biz::ExpandableListFormModel;
use strict;
use Bivio::Base 'Biz.ListFormModel';
# C<Bivio::Biz::ExpandableListFormModel> list form which can have extra rows
my($_IDI) = __PACKAGE__->instance_data_index;
sub EMPTY_AND_CANNOT_BE_SPECIFIED_FIELDS {
return [];
}
sub MUST_BE_SPECIFIED_FIELDS {
# The list of fields that are expected to have NULL or UNSPECIFIED
# L<Bivio::TypeError|Bivio::TypeError> on them if the row is to be considered ok
# to be empty. By default, this returns undef, in which case, this class
# does nothing in L<validate_row|"validate_row">.
#
# When you supply an array_ref, this code will go through those fields. If they
# are I<all> NULL or UNSPECIFIED, then all those errors will be cleared. You can
# then check on of the
return;
}
sub ROW_INCREMENT {
# number of empty rows to add to the list.
return 4;
}
sub execute_empty {
my($self) = @_;
# Copies submitted values
my($prev_self) = $self->get_request->unsafe_get(_key($self));
$self->internal_put({%{$prev_self->internal_get}})
if $prev_self;
return shift->SUPER::execute_empty(@_);
}
sub execute_empty_row {
my($self) = @_;
# Loads visible list fields.
foreach my $f (@{$self->get_info('visible_field_names')}) {
$self->internal_load_field($f)
if $self->get_list_model->has_keys($f);
}
return;
}
sub internal_initialize {
my($self) = @_;
# B<FOR INTERNAL USE ONLY>
my($info) = {
visible => [
{
name => 'add_rows',
type => 'OKButton',
constraint => 'NONE',
},
],
hidden => [
{
name => 'empty_row_count',
type => 'Integer',
constraint => 'NONE',
},
],
};
return $self->merge_initialize_info(
$self->SUPER::internal_initialize, $info);
}
sub internal_initialize_list {
my($self) = shift;
# Appends empty rows to the list.
my($list) = $self->SUPER::internal_initialize_list(@_);
my($req) = $self->get_request;
# COUPLING: FormModel caches the form for us so we can modify in place
my($form) = $self->internal_get_form($req);
my($prev_self) = $req->unsafe_get(_key($self));
my($erc) = $prev_self ? $prev_self->get('empty_row_count')
: $form ? $form->{$self->get_field_name_for_html('empty_row_count')}
: $self->ROW_INCREMENT;
$self->internal_put_field(empty_row_count => $erc);
$form->{$self->get_field_name_for_html('empty_row_count')} = $erc
if $form;
$list->append_empty_rows($erc);
return $list;
}
sub internal_load_field {
my($self, $form_field, $list_field) = @_;
# Loads I<form_field> from the list model's I<list_field> (defaults to
# (I<form_field>) if this isn't a redirect through add_rows.
return if $self->get_request->unsafe_get(_key($self));
$list_field ||= $form_field;
my($value) = $self->get_list_model->get($list_field);
$self->internal_put_field($form_field, $value)
if defined($value);
return;
}
sub is_empty_row {
my($self) = @_;
# Returns true if the L<MUST_BE_SPECIFIED_FIELDS|"MUST_BE_SPECIFIED_FIELDS"> are
# L<Bivio::Type::is_specified|Bivio::Type/"is_specified">.
# Calls SUPER::is_empty_row if MUST_BE_SPECIFIED_FIELDS is false.
foreach my $f (@{
$self->MUST_BE_SPECIFIED_FIELDS
|| return shift->SUPER::is_empty_row(@_),
}) {
return 0
if $self->get_field_type($f)->is_specified($self->unsafe_get($f));
}
foreach my $f (@{$self->EMPTY_AND_CANNOT_BE_SPECIFIED_FIELDS}) {
return 0
if $self->get_field_type($f)->is_specified($self->unsafe_get($f));
}
return 1;
}
sub validate {
my($self, $form_button) = @_;
# Responds to button click on 'add_rows', save the values on the
# request and redirects to the same task.
return shift->SUPER::validate(@_)
unless $self->unsafe_get('add_rows');
my($req) = $self->get_request;
# increment the empty_row count and redirect to the same task
$self->internal_put_field(empty_row_count =>
$self->get('empty_row_count') + $self->ROW_INCREMENT);
$req->put_durable(_key($self) => $self);
# Put last for testing
$req->server_redirect($req->get(qw(task_id auth_realm query path_info)));
# DOES NOT RETURN
}
sub validate_row {
my($self) = @_;
# Clears errors on L<MUST_BE_SPECIFIED_FIELDS|"MUST_BE_SPECIFIED_FIELDS">
# if L<is_empty_row|"is_empty_row">.
return unless my $cols = $self->MUST_BE_SPECIFIED_FIELDS;
return unless $self->is_empty_row;
foreach my $f (@$cols, @{$self->EMPTY_AND_CANNOT_BE_SPECIFIED_FIELDS}) {
next unless my $e = $self->get_field_error($f);
$self->internal_clear_error($f)
if $e->eq_null || $e->eq_unspecified;
}
return;
}
sub _key {
my($self) = @_;
# Returns the attribute key used on the request.
return __PACKAGE__ . '.' . ref($self);
}
1;