To create a backend form via ui_component, I define following in the config file to display buttons save and saveAndContinue Button

<item name="buttons" xsi:type="array">
    <item name="save" xsi:type="string">namespace\module\Block\Adminhtml\Edit\SaveButton</item>
    <item name="save_and_continue" xsi:type="string">namespace\module\Block\Adminhtml\Edit\SaveAndContinueButton</item>

Respectively, two files SaveButton.php and SaveAndContinueButton.php are created and both implement ButtonProviderInterface

As I know, button is mainly rendered from a getButtonData function. See SaveAndContinueButton.php

public function getButtonData()
    $TodoItemId = $this->getTodoItemId();
    $data = [];
    if ($TodoItemId) {
        $data = [
            'label' => __('Save and Continue Edit'),
            'class' => 'save',
            'data_attribute' => [
                'mage-init' => [
                    'button' => ['event' => 'saveAndContinueEdit'],
            'sort_order' => 80,
    return $data;

The data_attribute is where that I don't understand. How does it know which file to handle save request?

If we check the SaveButton.php, We saw

$data = [
    'label' => __('Save TodoItem'),
    'class' => 'save primary',
    'data_attribute' => [
        'mage-init' => ['button' => ['event' => 'save']],
        'form-role' => 'save',
    'sort_order' => 90,

I know in the ui_component config file, there is

<item name="submit_url" xsi:type="url" path="path/to/save"/>

Both action successfully execute same Save.php file and it makes sense. What confuse me much is data_attribute and how does SaveAndContinueButton pass parameter "back" so that it knows to stay at the same page instead of go to grid (normally grid is entry point of a form, aka edit page).

If we take another look at the deleteButton, it's another landscape

$data = [
    'label' => __('Delete'),
    'class' => 'delete',
    'on_click' => 'deleteConfirm(\'' . __(
        'Are you sure you want to do this?'
    ) . '\', \'' . $this->getDeleteUrl() . '\')',

    'sort_order' => 20,

It directly executes the onClick JavaScript event. Any idea/suggestion will be appreciated. thanks

One more question: what's the different of data_attribute and on_click? or advantage one over another one?

  • 1
    I have save and continue , but it redirects to magento admin page not found error
    – Jaisa
    Commented Feb 8, 2018 at 10:30
  • What are the files needed to add save and continue
    – Jaisa
    Commented Feb 8, 2018 at 10:31

1 Answer 1


I don't have a full explanation, but I have an idea.
All elements rendered with mage-init will/should be handled by some javascript code.
You are linking these buttons to a form, and the form is handled by this js file lib/web/mage/backend/form.js where a jquery ui widget is created.

These are the options for the widget

options: {
    handlersData: {
        save: {},
        saveAndContinueEdit: {
            action: {
                args: {
                    back: 'edit'
        preview: {
            target: '_blank'

you can see a saveAndContinueEdit in there somewhere inside handlersData.
Looking for the usages of handlersData you end up in _beforeSubmit where some magic happens (I don't really understand everything in there), and at one point _processData is called.
Moving to _processData you will see something like this

if (attrName === 'action') {
    data[attrName] = this._getActionUrl(attrValue);

this means that the action of the form is changed based on the button pressed.

the _getActionUrl function looks like this

_getActionUrl: function(data) {
    if ($.type(data) === 'object') {
        return this._buildURL(this.oldAttributes.action, data.args);
    } else {
        return $.type(data) === 'string' ? data : this.oldAttributes.action;

you can see in there data.args involved. The same variable in the widget options for saveAndContinueEdit.

Conclusion: When you set the role saveAndContinueEdit toa submit button, the action of the form is changed via js and back/edit is added to the url.

on_click is transformed to the onclick event and simply called.
I honestly have no idea why there are 2 ways of doing this. Maybe the delete actions didn't get refactored yet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.