[html-formfu] HTML::FormFu::Model::DBIC and Many-to-many
Ascii King
tech at swattermatter.com
Sun Sep 27 22:12:04 GMT 2009
Carl Franks wrote:
> I don't think it's currently possible in a single step, to both select
> which one's to relate, and edit them.
> It's either a multi-value element to select them, or a Repeatable
> block to edit the already related rows.
>
> Carl
>
>
This is something I have been struggling with for over a year now. It is
possible to do exactly what Nigel is asking. As near as I can tell, the
reason this does not seem to work is because FormFu wants the id field
in a repeatable element to be a Hidden element. So, you create a new id
field in your intermediary table that can be the hidden id field and you
set your repeatable nested_name to the has_many relationship, not the
many-to-many. You use the many-to-many relationship when you want to
display it.
Here's my example:
Each hero can have many skills. Each hero's skill has a rank for that
hero only.
Batman can jump over a wall. Skill -> Jump with Rank -> 2
Superman can leap tall buildings. Skill -> Jump with Rank -> 5
package My::Hero;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('hero');
__PACKAGE__->add_columns(qw/hero_id hero_name/);
__PACKAGE__->set_primary_key('hero_id');
__PACKAGE__->has_many('hero_skill' => 'My::Result::HeroSkill', 'hero_id' );
__PACKAGE__->many_to_many('skills' => 'hero_skill', 'skill_id');
Here is the intermediary table. It includes Rank because that is particulair to each hero.
Notice I've created a new primary key rather than using the hero_id, skill_id combination key. This is important.
package My::HeroSkill;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('hero_skill');
__PACKAGE__->add_columns(qw/hero_skill_id hero_id skill_id rank/);
__PACKAGE__->set_primary_key('hero_skill_id');
__PACKAGE__->belongs_to('hero_id' => 'My::Result::Hero');
__PACKAGE__->belongs_to('skill_id' => 'My::Result::Skill');
package My::Skill;
use base 'DBIx::Class';
__PACKAGE__->load_components('Core');
__PACKAGE__->table('skill');
__PACKAGE__->add_columns(qw/skill_id skill_name/);
__PACKAGE__->set_primary_key('skill_id');
__PACKAGE__->has_many('hero_skill' => 'My::Result::HeroSkill', 'skill_id');
__PACKAGE__->many_to_many('heroes' => 'hero_skill', 'hero_id');
When you are building your form's config file, just remember to use the
has_many relationship as the nested_name.
Since the skills are going to come from a pick list, I have set the
Select element resultset to "Skill" so it uses the Skill table.
hero_form.yml
------------------------
---
indicator: submitted
elements:
# HERO_NAME --
- type: Text
name: hero_name
label: Name
# THECOUNT --
- type: Hidden
name: skill_count
# ** REPEAT SKILLS --
- type: Repeatable
nested_name: hero_skill
counter_name: skill_count
model_config:
empty_rows: 1
new_rows_max: 100
elements:
# HERO_SKILL_ID --
- type: Hidden
name: hero_skill_id
# SKILL --
- type: Select
name: skill_id
label: Skill
empty_first: 1
model_config:
resultset: Skill
id_column: skill_id
label_column: skill_name
attributes:
order_by: skill_name
# RANK --
- type: Text
name: rank
label: Rank
# DELETE HERO SKILL --
- type: Checkbox
name: remove_skill
label: Delete
model_config:
delete_if_true: 1
# SUBMIT --
- type: Submit
name: submitted
value: Submit
This will create a form that allows you to create Heroes with multiple
skills where each skill has a unique rank.
To display your hero, you then use the many-to-many relationship as normal.
list_hero.tt2
---------------------
<table>
<thead>
<th>Name</th>
<th>Skills</th>
</thead>
[% FOREACH hero IN object -%]
</tr>
<td>[% hero.hero_name %]</a></td>
<td>
[% FOREACH unique_skill = hero.skills %]
[% unique_skill.skill_name %] [[% unique_skill.hero_skill.rank
%]]<br />
[% END %]
</td>
</tr>
[% END -%]
</table>
Please notice the odd relationship to get the rank to display. [%
unique_skill.hero_skill.rank %]
If there is some data-integrity reason why I can't do it this way,
please tell me. I hope this helps someone.
More information about the HTML-FormFu
mailing list