I do the very same thing with a contacts hasMany addresses and a
contacts hasMany phones type relations
The form uses some simple scriptaculous/prototype javascript. To
duplicate and insert an html template set to display=none. It changes
the display and updates the field id's each time the "add" button is
clicked.
This builds the form controls in a cakephp freindly way so I can call
SaveAll. In my model beforeSave I strip out any data items that are
still in the template format.
I took a glance at the link Dwayne provided and it looks to be fairly
complete I might replace what I have with his as mine is more of a one
off solution in its current state.
I thought I would share it as it may give you some other ideas of
implementation and integrating the dynamicField solution into the
CakePHP form.
In my view I have the following div's The first one is the Template
and is hidden the second div is visible and by defaults automatically
shows the Phones associated with the Contact.
<div id="contactPhoneTemplate" style="display: none">
<div id="#{model}#{iteration}div">
<input
name="data[#{model}][#{iteration}][deleted]" value="false"
id="#{model}#{iteration}Deleted" type="hidden">
<span>
<input type="hidden" value="0"
id="#{model}#{iteration}Optout_"
name="data[#{model}][#{iteration}][optout]">
<input type="checkbox"
id="#{model}#{iteration}Optout" value="1"
name="data[#{model}][#{iteration}][optout]">
<label
for="#{model}#{iteration}Optout">Optout</label>
</span>
<span><input
name="data[#{model}][#{iteration}][value]"
maxlength="128" value="" id="#{model}#{iteration}Value" type="text"></
span>
<span><select
name="data[#{model}][#{iteration}][label]"
id="#{model}#{iteration}Label">
<option value="Work">Work</option>
<option value="Home">Home</option>
<option value="Mobile"
selected="selected">Mobile</option>
<option value="Home Fax">Home
Fax</option>
<option value="Work Fax">Work
Fax</option>
<option value="Pager">Pager</option>
<option value="Other">Other</option>
</select>
</span>
<span><a class="cmgr-subtle"
onclick="removePhone(#{iteration});">remove</a></span>
</div>
</div>
<?php
echo $ajax->div('contact-phones');
if(!empty($this->data['Phone'])){
$phones = $this->data['Phone'];
foreach ($phones as $i=>$phone){
echo '<div id="Phone'.$i.'div">';
echo $form->input('Phone.'.$i.'.id');
echo $form->input('Phone.'.
$i.'.optout',array('div'=>false,'before'=>'<span>','after'=>'</
span>'));
echo $form->input('Phone.'.
$i.'.deleted',array('type'=>'hidden','value'=>'false'));
echo $form->input('Phone.'.
$i.'.value',array('label'=>false,'div'=>false,'before'=>'<span>','after'=>'</
span>'));
echo $form->input('Phone.'.
$i.'.label',array('options'=>array('Work'=>'Work','Home'=>'Home','Mobile'=>'Mobile','Home
Fax'=>'Home Fax','Work Fax'=>'Work
Fax','Pager'=>'Pager','Other'=>'Other'),'label'=>false,'div'=>false,'before'=>'<span>','after'=>'</
span>'));
echo '<span><a class="cmgr-subtle"
onclick="removePhone('.
$i.');">remove</a></span>';
echo '</div>';
}
}
echo $ajax->divEnd('contact-phones');
?>
</div>
The JavaScript first finds the max phone iteration. It grabs a copy of
the 'contactPhoneTemplate' updates the id's and name values and then
inserts the innerHTML at the end of div 'contact-phones' in the form.
This is the function tied to the "Add" button Next to my phones:
function addPhone(){
var iteration = 0;
for (iteration=0;iteration<=100;iteration=iteration+1)
{
var targetDiv = 'Phone'+iteration+'div';
if(!$(targetDiv)){
break;
}
}
var myDiv=$('contactPhoneTemplate');
$('contact-phones').insert(new
Template(myDiv.innerHTML).evaluate({model: 'Phone',iteration:
iteration}));
}
On Feb 16, 11:53 am, Yaron <[email protected]> wrote:
> Dwayne, thanks for the detailed reply :)
> I'll try it later today when I have time and update here.
>
> Thank u guys!
>
> On Feb 15, 9:36 pm, Dwayne Hanekamp <[email protected]> wrote:
>
>
>
>
>
>
>
> > Hello Yaron,
>
> > For this u need to use the jquery plugin for dynamic forms
> > (http://www.quackfuzed.com/demos/jQuery/dynamicField/).
> > The Librarian can click on a button and the new fields will appear.
> > For each field use a default name with [] at the end (which will make
> > it stack like a array) example: data[][book_id] after the fields have
> > been submitted, u will save them via a foreach-luss. something like:
>
> > foreach($data as $data){
> > $this->Book->create();
> > $this->Book->save($data);
>
> > }
>
> > Thats pretty much it! At least if i understand your question right!
>
> > On 15 feb, 18:56, Yaron <[email protected]> wrote:
>
> > > Hi,
> > > Suppose I have a book-borrowing application with a Customers table, a
> > > Books table and Borrowings table (customer_id, book_id and date
> > > fields).
> > > The borrowing view has three fields: customer, date and book (this
> > > field is a drop-down-box). Usually, a customer borrows more than a
> > > single book at once. The librarian does want to add one book at a
> > > time, but enter as many books as needed on the same view: when he
> > > picks a book, a new book field appears. Another book pick adds another
> > > book field, etc. When the librarian hits "Save" every book gets a
> > > record, when the "customer" and "date" fields serve all book records.
> > > Help needed please, since I have no idea how to do that. Thanks!
--
Our newest site for the community: CakePHP Video Tutorials
http://tv.cakephp.org
Check out the new CakePHP Questions site http://ask.cakephp.org and help others
with their CakePHP related questions.
To unsubscribe from this group, send email to
[email protected] For more options, visit this group at
http://groups.google.com/group/cake-php