Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Enabling Inline Edit in the Grid

Enabling Inline Edit in the Grid

~8 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026

Inline edit lets you edit and save cell values directly in the grid, without opening the form - fully built into Magento_Ui already; only a declaration and a controller are needed.

editorConfig in listing.xml

<listing>
    <!-- ... dataSource, columns as in chapter 15 ... -->

    <columns name="testimonial_columns">
        <settings>
            <editorConfig>
                <param name="clientConfig" xsi:type="array">
                    <item name="saveUrl" xsi:type="url" path="mironsoft_testimonial/testimonial/inlineEdit"/>
                    <item name="validateBeforeSave" xsi:type="boolean">false</item>
                </param>
                <param name="indexField" xsi:type="string">testimonial_id</param>
                <param name="enabled" xsi:type="boolean">true</param>
            </editorConfig>
        </settings>

        <column name="customer_name">
            <settings>
                <filter>text</filter>
                <editor>
                    <editorType>text</editorType>
                    <validation>
                        <rule name="required-entry" xsi:type="boolean">true</rule>
                    </validation>
                </editor>
                <label translate="true">Customer</label>
            </settings>
        </column>
        <column name="is_active">
            <settings>
                <options class="Mironsoft\Testimonial\Model\Source\IsActive"/>
                <filter>select</filter>
                <editor>
                    <editorType>select</editorType>
                </editor>
                <dataType>select</dataType>
                <label translate="true">Status</label>
            </settings>
        </column>
    </columns>
</listing>

Every column meant to be editable gets an <editor> element with a matching editorType (text, select, date, textarea). Columns without an <editor> - like the actions or image column - automatically stay read-only.

The InlineEdit controller

app/code/Mironsoft/Testimonial/Controller/Adminhtml/Testimonial/InlineEdit.php
<?php

declare(strict_types=1);

namespace Mironsoft\Testimonial\Controller\Adminhtml\Testimonial;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\Controller\Result\JsonFactory;
use Mironsoft\Testimonial\Api\TestimonialRepositoryInterface;

/**
 * Persists grid inline-edit changes for one or more testimonials.
 */
class InlineEdit extends Action implements HttpPostActionInterface
{
    public const ADMIN_RESOURCE = 'Mironsoft_Testimonial::save';

    /**
     * @param Context $context Backend action context.
     * @param TestimonialRepositoryInterface $testimonialRepository Loads/saves testimonials.
     * @param JsonFactory $resultJsonFactory Factory for the JSON result.
     */
    public function __construct(
        Context $context,
        private readonly TestimonialRepositoryInterface $testimonialRepository,
        private readonly JsonFactory $resultJsonFactory,
    ) {
        parent::__construct($context);
    }

    /**
     * Applies the posted cell changes and reports per-row errors, if any.
     *
     * @return Json
     */
    public function execute(): Json
    {
        $result = $this->resultJsonFactory->create();
        $items = (array) $this->getRequest()->getParam('items', []);
        $errorMessages = [];

        if (!$items) {
            return $result->setData([
                'messages' => [__('Please correct the data sent.')],
                'error' => true,
            ]);
        }

        foreach ($items as $itemData) {
            $testimonialId = (int) ($itemData['testimonial_id'] ?? 0);

            try {
                $testimonial = $this->testimonialRepository->getById($testimonialId);
                $testimonial->setData(array_merge($testimonial->getData(), $itemData));
                $this->testimonialRepository->save($testimonial);
            } catch (\Throwable $exception) {
                $errorMessages[] = '[Row ID: ' . $testimonialId . '] ' . $exception->getMessage();
            }
        }

        return $result->setData([
            'messages' => $errorMessages,
            'error' => (bool) $errorMessages,
        ]);
    }
}

The response follows a fixed contract: error (boolean) and messages (array of strings) - that's exactly what the JavaScript editor component expects to display per-row error icons and tooltips.

Achtung: array_merge($testimonial->getData(), $itemData) matters here: $itemData only contains the fields that were actually changed on the edited row, not the full record. A direct setData($itemData) without merging would overwrite every field not sent along (for example testimonial_text) with null.

Tipp: Inline edit and the modifiers from chapter 13 complement rather than compete with each other: modifiers control the full form, inline edit the quick change of individual fields right in the grid - both ultimately go through the same TestimonialRepositoryInterface.