Skip to content

Commit

Permalink
Implement inline creation of records.
Browse files Browse the repository at this point in the history
* Builds on the editable cols component with GridFieldAddNewInlineButton.
* Closes #2.
  • Loading branch information
ajshort committed Feb 8, 2013
1 parent c10810c commit 692453b
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -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.
Expand Down
142 changes: 142 additions & 0 deletions code/GridFieldAddNewInlineButton.php
@@ -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);
}
}

}
4 changes: 2 additions & 2 deletions code/GridFieldEditableColumns.php
Expand Up @@ -110,7 +110,7 @@ public function getURLHandlers($grid) {
* @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();
Expand Down Expand Up @@ -162,7 +162,7 @@ protected function getFields(GridField $grid, DataObjectInterface $record) {
* @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());
Expand Down
8 changes: 8 additions & 0 deletions css/GridFieldExtensions.css
Expand Up @@ -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
*/
Expand Down
33 changes: 33 additions & 0 deletions javascript/GridFieldExtensions.js
Expand Up @@ -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
*/
Expand Down
3 changes: 3 additions & 0 deletions templates/GridFieldAddNewInlineButton.ss
@@ -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>
13 changes: 13 additions & 0 deletions templates/GridFieldAddNewInlineRow.ss
@@ -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>

0 comments on commit 692453b

Please sign in to comment.