Implement inline creation of records.

* Builds on the editable cols component with GridFieldAddNewInlineButton.
* Closes #2.
This commit is contained in:
ajshort 2013-02-09 02:19:30 +11:00
parent c10810c3f6
commit 692453bf9b
7 changed files with 202 additions and 2 deletions

View File

@ -4,6 +4,7 @@ SilverStripe Grid Field Extensions Module
This module provides a number of useful grid field components:
* `GridFieldAddExistingSearchButton` - a more advanced search form for adding items.
* `GridFieldAddNewInlineButton` - builds on `GridFieldEditableColumns` to allow inline creation of records.
* `GridFieldAddNewMultiClass` - lets the user select from a list of classes to create a new record from.
* `GridFieldEditableColumns` - allows inline editing of records.
* `GridFieldOrderableRows` - drag and drop re-ordering of rows.

View File

@ -0,0 +1,142 @@
<?php
/**
* Builds on the {@link GridFieldEditableColumns} component to allow creating new records.
*/
class GridFieldAddNewInlineButton implements GridField_HTMLProvider, GridField_SaveHandler {
private $fragment;
private $title;
/**
* @param string $fragment the fragment to render the button in
*/
public function __construct($fragment = 'buttons-before-left') {
$this->setFragment($fragment);
$this->setTitle(_t('GridFieldExtensions.ADD', 'Add'));
}
/**
* Gets the fragment name this button is rendered into.
*
* @return string
*/
public function getFragment() {
return $this->fragment;
}
/**
* Sets the fragment name this button is rendered into.
*
* @param string $fragment
*/
public function setFragment($fragment) {
$this->fragment = $fragment;
}
/**
* Gets the button title text.
*
* @return string
*/
public function getTitle() {
return $this->title;
}
/**
* Sets the button title text.
*
* @param string $title
*/
public function setTitle($title) {
$this->title = $title;
}
public function getHTMLFragments($grid) {
$class = $grid->getModelClass();
$fragment = $this->getFragment();
if(!$editable = $grid->getConfig()->getComponentByType('GridFieldEditableColumns')) {
throw new Exception('Inline adding requires the editable columns component');
}
if(!singleton($class)->canCreate()) {
return false;
}
Requirements::javascript(THIRDPARTY_DIR . '/javascript-templates/tmpl.js');
GridFieldExtensions::include_requirements();
$data = new ArrayData(array(
'Title' => $this->getTitle(),
));
return array(
$fragment => $data->renderWith(__CLASS__),
'after' => $this->getRowTemplate($grid, $editable)
);
}
private function getRowTemplate(GridField $grid, GridFieldEditableColumns $editable) {
$class = $grid->getModelClass();
$columns = new ArrayList();
$handled = array_keys($editable->getDisplayFields($grid));
$record = new $class();
$fields = $editable->getFields($grid, $record);
foreach($grid->getColumns() as $column) {
if(in_array($column, $handled)) {
$field = $fields->dataFieldByName($column);
$field->setName(sprintf(
'%s[%s][{%%=o.num%%}][%s]', $grid->getName(), __CLASS__, $field->getName()
));
$content = $field->Field();
} else {
$content = null;
}
$attrs = '';
foreach($grid->getColumnAttributes($record, $column) as $attr => $val) {
$attrs .= sprintf(' %s="%s"', $attr, Convert::raw2att($val));
}
$columns->push(new ArrayData(array(
'Content' => $content,
'Attributes' => $attrs,
'IsActions' => $column == 'Actions'
)));
}
return $columns->renderWith('GridFieldAddNewInlineRow');
}
public function handleSave(GridField $grid, DataObjectInterface $record) {
$value = $grid->Value();
if(!isset($value[__CLASS__]) || !is_array($value[__CLASS__])) {
return;
}
$class = $grid->getModelClass();
$editable = $grid->getConfig()->getComponentByType('GridFieldEditableColumns');
$form = $editable->getForm($grid, $record);
if(!singleton($class)->canCreate()) {
return;
}
foreach($value[__CLASS__] as $fields) {
$item = new $class();
$form->loadDataFrom($fields, Form::MERGE_CLEAR_MISSING);
$form->saveInto($item);
$grid->getList()->add($item);
}
}
}

View File

@ -110,7 +110,7 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
* @param DataObjectInterface $record
* @return FieldList
*/
protected function getFields(GridField $grid, DataObjectInterface $record) {
public function getFields(GridField $grid, DataObjectInterface $record) {
$cols = $this->getDisplayFields($grid);
$fields = new FieldList();
$class = $grid->getList()->dataClass();
@ -162,7 +162,7 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
* @param DataObjectInterface $record
* @return Form
*/
protected function getForm(GridField $grid, DataObjectInterface $record) {
public function getForm(GridField $grid, DataObjectInterface $record) {
$fields = $this->getFields($grid, $record);
$form = new Form($this, null, $fields, new FieldList());

View File

@ -86,6 +86,14 @@
max-width: none !important;
}
.ss-gridfield-add-new-inline span.readonly {
color: #FFF !important;
}
.ss-gridfield-add-new-inline .col-buttons {
text-align: right;
}
/**
* GridFieldOrderableRows
*/

View File

@ -72,6 +72,39 @@
}
});
/**
* GridFieldAddNewInlineButton
*/
$(".ss-gridfield-add-new-inline").entwine({
onclick: function() {
var tmpl = window.tmpl;
var grid = this.getGridField();
var row = grid.find(".ss-gridfield-add-inline-template");
var num = grid.data("add-inline-num") || 1;
tmpl.cache["ss-gridfield-add-inline-template"] = tmpl(row.html());
grid.find("tbody").append(tmpl("ss-gridfield-add-inline-template", { num: num }));
grid.find(".ss-gridfield-no-items").hide();
grid.data("add-inline-num", num + 1);
return false;
}
});
$(".ss-gridfield-delete-inline").entwine({
onclick: function() {
var msg = ss.i18n._t("GridFieldExtensions.CONFIRMDEL", "Are you sure you want to delete this?");
if(confirm(msg)) {
this.parents("tr").remove();
}
return false;
}
});
/**
* GridFieldAddNewMultiClass
*/

View File

@ -0,0 +1,3 @@
<button href="$Link" class="ss-gridfield-add-new-inline ss-ui-action-constructive ss-ui-button" data-icon="add">
$Title
</button>

View File

@ -0,0 +1,13 @@
<script type="text/x-tmpl" class="ss-gridfield-add-inline-template">
<tr class="ss-gridfield-inline-new">
<% loop $Me %>
<% if $IsActions %>
<td$Attributes>
<button class="ss-gridfield-delete-inline gridfield-button-delete ss-ui-button" data-icon="cross-circle"></button>
</td>
<% else %>
<td$Attributes>$Content</td>
<% end_if %>
<% end_loop %>
</tr>
</script>