Skip to content

Commit 7cdd144

Browse files
committed
Add ability to write on new row so ID is available
1 parent 0560619 commit 7cdd144

File tree

2 files changed

+77
-15
lines changed

2 files changed

+77
-15
lines changed

client/js/ManyField.src.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@
3939
parents = $(this).parents('.manyfield__holder');
4040

4141
$.get($(this).attr('href'), { index: parents.find('.manyfield__row').length }, function(data) {
42-
parents.find('.manyfield__row').last().after(data)
42+
var rows = parents.find('.manyfield__row').last()
43+
44+
if (rows && rows.length) {
45+
rows.after(data)
46+
} else {
47+
parents.find('.manyfield__outer').append(data)
48+
}
4349

4450
wrapManyFields()
4551

src/ManyField.php

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use SilverStripe\Control\Director;
1111
use SilverStripe\Control\Controller;
1212
use SilverStripe\Forms\FormField;
13+
use SilverStripe\Forms\HiddenField;
1314
use SilverStripe\Security\SecurityToken;
1415
use SilverStripe\Core\Injector\Injector;
1516
use SilverStripe\Control\HTTPResponse;
@@ -36,6 +37,9 @@ class ManyField extends CompositeField
3637
protected $canAdd = true;
3738

3839
/**
40+
* Can records be removed from the list - useful for displaying just an
41+
* inline edit form.
42+
*
3943
* @var boolean
4044
*/
4145
protected $canRemove = true;
@@ -55,6 +59,16 @@ class ManyField extends CompositeField
5559
*/
5660
protected $addLabel = 'Add';
5761

62+
/**
63+
* Does creating a new row automatically call write to the database?
64+
*
65+
* If you use things such as UploadField which requires an ID then it is
66+
* best to set this to true
67+
*
68+
* @var boolean
69+
*/
70+
protected $callWriteOnNewRow = false;
71+
5872
/**
5973
* @var array
6074
*/
@@ -80,20 +94,27 @@ public function __construct($name, $children = null) {
8094
}
8195

8296
$this->children = new FieldList();
97+
8398
$this->brokenOnConstruct = false;
8499

85100
FormField::__construct($name, null);
86101
}
87102

88103
/**
89-
* A callback to customise a given form field instance. Must take 3
90-
* arguments `$field, $index, $manyField`.
104+
* A callback to customise a given form field instance. Must take 4
105+
* arguments `$field, $index, $manyField, $value`.
91106
*
92107
* @param string $field
93108
* @param callable $callback
94109
*/
95110
public function addFieldCallback($field, $callback) {
96-
$this->fieldCallbacks[$field] = $callback;
111+
if (!isset($this->fieldCallbacks[$field])) {
112+
$this->fieldCallbacks[$field] = [];
113+
}
114+
115+
$this->fieldCallbacks[$field][] = $callback;
116+
117+
return $this;
97118
}
98119

99120
/**
@@ -214,6 +235,18 @@ public function hasData()
214235
return true;
215236
}
216237

238+
/**
239+
* @param boolean $bool
240+
*
241+
* @return $this
242+
*/
243+
public function setCallWriteOnNewRow($bool)
244+
{
245+
$this->callWriteOnNewRow = $bool;
246+
247+
return $this;
248+
}
249+
217250
/**
218251
* Set the field value.
219252
*
@@ -276,7 +309,7 @@ public function setValue($value, $data = null)
276309
}
277310
}
278311

279-
parent::setValue($value, $data);
312+
return parent::setValue($value, $data);
280313
}
281314

282315
/**
@@ -290,7 +323,6 @@ public function FieldList() {
290323
$index = 0;
291324

292325
if ($this->value) {
293-
294326
foreach ($this->value as $record) {
295327
$output->push($this->generateRow($index++, $record));
296328
}
@@ -315,13 +347,25 @@ public function generateRow($index, $value = null)
315347
$row = CompositeField::create();
316348
$row->addExtraClass("row manyfield__row");
317349

350+
if (!$value && $this->callWriteOnNewRow) {
351+
// create a new value
352+
$value = $this->createPhysicalRecord();
353+
}
354+
318355
foreach ($this->manyChildren as $child) {
319356
$field = clone $child;
320357
$field->name = $this->name . '['.$child->name . ']['. $index . ']';
321-
$field->setValue(($value) ? $value->{$child->name} : null);
358+
359+
if ($value && $value->hasMethod($child->Name)) {
360+
$field->setValue($value->{$child->name}());
361+
} else {
362+
$field->setValue(($value) ? $value->{$child->name} : null);
363+
}
322364

323365
if (isset($this->fieldCallbacks[$child->name])) {
324-
call_user_func($this->fieldCallbacks[$name], $field, $index, $this);
366+
foreach ($this->fieldCallbacks[$child->name] as $cb) {
367+
call_user_func($cb, $field, $index, $this, $value);
368+
}
325369
}
326370

327371
$row->push($field);
@@ -332,6 +376,16 @@ public function generateRow($index, $value = null)
332376
return $row;
333377
}
334378

379+
public function createPhysicalRecord()
380+
{
381+
$create = Injector::inst()->create($this->value->dataClass());
382+
$create->write();
383+
384+
$this->value->add($create);
385+
386+
return $create;
387+
}
388+
335389
public function AbsoluteLink($action = null)
336390
{
337391
return Director::absoluteURL($this->Link($action));
@@ -349,7 +403,7 @@ public function updateRelation(DataObjectInterface $record, $delete = true)
349403
$removed = [];
350404

351405
// if no value then we should clear everything out
352-
if (!$this->value) {
406+
if (!$this->value && $this->canRemove) {
353407
if ($delete) {
354408
foreach ($existing as $row) {
355409
$row->delete();
@@ -366,12 +420,14 @@ public function updateRelation(DataObjectInterface $record, $delete = true)
366420
throw new Exception('Missing ID field in ManyMany field list.');
367421
}
368422

369-
if (!isset($this->value['ID'][$row->ID])) {
370-
// missing so delete or remove.
371-
if ($delete) {
372-
$existing->find('ID', $row->ID)->delete();
373-
} else {
374-
$existing->removeById($row->ID);
423+
if ($this->canRemove) {
424+
if (!isset($this->value['ID'][$row->ID])) {
425+
// missing so delete or remove.
426+
if ($delete) {
427+
$existing->find('ID', $row->ID)->delete();
428+
} else {
429+
$existing->removeById($row->ID);
430+
}
375431
}
376432
}
377433
}

0 commit comments

Comments
 (0)