PHPackages                             nyeholt/silverstripe-multirecordeditor - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. nyeholt/silverstripe-multirecordeditor

ActiveSilverstripe-vendormodule[Utility &amp; Helpers](/categories/utility)

nyeholt/silverstripe-multirecordeditor
======================================

A module for editing multiple records in a single interface.

33.7k2PHP

Since Dec 17Pushed 6y ago1 watchersCompare

[ Source](https://github.com/nyeholt/silverstripe-multirecordeditor)[ Packagist](https://packagist.org/packages/nyeholt/silverstripe-multirecordeditor)[ RSS](/packages/nyeholt-silverstripe-multirecordeditor/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependenciesVersions (2)Used By (0)

Multi Record Editing field
==========================

[](#multi-record-editing-field)

A field for editing multiple fields in a single editing interface.

Requirements
------------

[](#requirements)

- SilverStripe ^4.1

Installation
------------

[](#installation)

License
-------

[](#license)

See [License](license.md)

Problem being solved
--------------------

[](#problem-being-solved)

In some sites, it is desirable to remove some complexity from the editing process around managing objects related to pages, and only allow editing of those objects instead of full control over adding and removing them.

By making a gridfield available for power users to add, re-order and remove objects, and then presenting just the editable fields for the objects to content, both usage models can be catered for.

Documentation
-------------

[](#documentation)

```
private static $has_many = array('Elements' => 'BaseElement');

$editor = MultiRecordEditingField::create('Elements', 'Content Cells', $this->Elements());
$fields->addFieldToTab('Root.Elements', $editor);

```

**Example**

```
class Page extends SiteTree {

	private static $has_many = array(
        'Cells'      => 'BasicContent',
    );

    public function getCMSFields()
    {
        $fields = parent::getCMSFields();

        $editor = MultiRecordEditingField::create('ContentCellEditor', 'Content Cells', $this->Cells());
        $fields->addFieldToTab('Root.ContentCells', $editor);

        if (Permission::check('ADMIN')) {
            $config = GridFieldConfig_RecordEditor::create();
            $grid = GridField::create('Cells', 'Cells', $this->Cells(), $config);
            $fields->addFieldToTab('Root.ContentCells', $grid);
        }

        return $fields;
    }
}

class Page_Controller extends ContentController {}

class BasicContent extends DataObject
{
    private static $db = array(
        'Title'     => 'Varchar(255)',
        'Description'   => 'Text',
        'Content'       => 'HTMLText',
    );

    private static $has_one = array(
        'Parent'        => 'Page',
    );

    private static $many_many = array(
        'Images'        => 'Image',
    );

    public function getCMSFields()
    {
        $fields = parent::getCMSFields();

        $uploadField = UploadField::create('Images', 'Images', $this->Images());
        $uploadField->setAllowedFileCategories('image');
        $fields->replaceField('Images', $uploadField);

        return $fields;
    }
}
```

Alternatively, the top level items may be inserted on separate tabs

```
		// in Page::getCMSFields()
		$i = 0;
        foreach ($this->Cells() as $cell) {
            $editor = MultiRecordEditingField::create('ContentCellEditor' . (++$i), $cell->Title, ArrayList::create(array($cell)));
            $editor->setUseToggles(false);
            $fields->addFieldToTab('Root.' . $cell->Title, $editor);
        }
```

**Multi-edit-ception?**

The `MultiRecordEditingField` supports nesting of other `MultiRecordEditingField`s. When the field detects a `MultiRecordEditingField`in the set of fields to edit, that field is added as another nested toggle field inside the parent set of fields for editing.

**Custom fields**

The `MultiRecordEditingField` uses the output of `getCMSFields` when building the fieldlist used for editing. To provide an alternate set of fields, define a `multiEditFields` method that returns a `FieldList` object.

Additionally, the `MultiRecordEditingField` calls the `updateMultiEditFields`extension hook on the *record* being edited to allow extensions a chance to change the fields.

**Frontend usage**

Pass in a boolean flag during construction

```
MultiRecordEditingField::create('ContentCellEditor', 'Content Cells', $this->Cells(), $frontend = true);

```

This will trigger the lookup of fields using `getFrontEndFields()` instead of getCMSFields().

Screenshots
-----------

[](#screenshots)

The above allows admin users to control what elements are available in the page for editing.

[![Admin view](screenshots/multi-edit.png)](screenshots/multi-edit.png)

While content authors are provided an in-page view for editing items.

[![Expanded editing view](screenshots/multi-edit-expanded.png)](screenshots/multi-edit-expanded.png)

Or set on different tabs.

[![Tabbed editing view](screenshots/multi-edit-tabbed.png)](screenshots/multi-edit-tabbed.png)

Maintainers
-----------

[](#maintainers)

- Marcus Nyeholt

Bugtracker
----------

[](#bugtracker)

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity22

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/25cb1c56a7ab949d1e6b28a2a04862ce1cffe1799a291e1797f8dfd33cd83716?d=identicon)[nyeholt](/maintainers/nyeholt)

---

Top Contributors

[![nyeholt](https://avatars.githubusercontent.com/u/161730?v=4)](https://github.com/nyeholt "nyeholt (7 commits)")

### Embed Badge

![Health badge](/badges/nyeholt-silverstripe-multirecordeditor/health.svg)

```
[![Health](https://phpackages.com/badges/nyeholt-silverstripe-multirecordeditor/health.svg)](https://phpackages.com/packages/nyeholt-silverstripe-multirecordeditor)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
