I actualized Magento to version 2.1 and my buttons stopped working. I'm not sure what I've changed. Actual version of files below.
My problem is to send save request to proper action (before it were working by ajax.) to controller action. Now if it even redirect page. I can't get post data on it. (is empty array).
settings_form.xml
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">settings_form.correctemail_settings_form_data_source</item>
<item name="deps" xsi:type="string">settings_form.correctemail_settings_form_data_source</item>
</item>
<item name="label" xsi:type="string" translate="true">Sample Form</item>
<item name="layout" xsi:type="array">
<item name="type" xsi:type="string">tabs</item>
</item>
<item name="buttons" xsi:type="array">
<item name="save" xsi:type="string">iDesign\Correctemail\Block\Adminhtml\Buttons\Save</item>
<item name="update" xsi:type="array">
<item name="name" xsi:type="string">update</item>
<item name="label" xsi:type="string">Save Settings</item>
<item name="class" xsi:type="string">primary</item>
<item name="url" xsi:type="string">*/*/save</item>
</item>
</item>
</argument>
<dataSource name="correctemail_settings_form_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">iDesign\Correctemail\Model\Settings\DataProvider</argument>
<argument name="name" xsi:type="string">correctemail_settings_form_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">settings_id</argument>
<argument name="requestFieldName" xsi:type="string">settings_id</argument>
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
</item>
<item name="config" xsi:type="array">
<item name="submit_url" xsi:type="url" path="*/*/*"/>
</item>
</argument>
</argument>
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
</item>
</argument>
</dataSource>
<fieldset>
...
</fieldset>
Block/Adminhtml/Buttons/Save.php
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
class Save implements ButtonProviderInterface
{
public function getButtonData()
{
return [
'label' => 'Save',
'class' => 'save primary',
'data_attribute' => [
'mage-init' => [
'button' => ['event' => 'save'],
],
],
'sort_order' => 80,
];
}
}
GenericButton.php
class GenericButton
{
/**
* @var Context
*/
protected $context;
/**
* @param Context $context
*/
public function __construct(Context $context)
{
$this->context = $context;
}
/**
* Return Settings ID
*
* @return int
*/
public function getSettingsId()
{
return 1;
}
/**
* Generate url by route and parameters
*
* @param string $route
* @param array $params
* @return string
*/
public function getUrl($route = '', $params = [])
{
return $this->context->getUrlBuilder()->getUrl($route, $params);
}
}
When I Inspect button html I have inside
onclick="location.href=... myModuleName/index/index ... (why?)
Other thing is. Why after reload my url gets at the end /undefined string
mage.dev/index.php/admin/ModuleName/settings/index/settings_id/1/key/9a71fd4a4f84367a354a134e399addc67dd95868a29651b37f6a4083ecd0fc05/undefined
6 Answers 6
Yo, whats up guys. I just had to wrestle with this in 2.1.9 and think I may have a legit answer.
All of these answers are close, but none seem to be completely correct so far. I'll explain how I figured this out.
Unfortuantely, for any of us that have worked with any depth in Magento 2, likely we've come to realize that if you want to do anything... you need to be able to trace core code. Which... is difficult- with all the knockout , xml... fun.
Enough nonsense. Lets get to it.
First, save button:
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">educationfiles_edit.educationfiles_edit_data_source</item>
<item name="deps" xsi:type="string">educationfiles_edit.educationfiles_edit_data_source</item>
</item>
<item name="layout" xsi:type="array">
<item name="type" xsi:type="string">tabs</item>
</item>
<item name="buttons" xsi:type="array">
<item name="manage" xsi:type="array">
<item name="name" xsi:type="string">manage</item>
<item name="label" xsi:type="string" translate="true">Manage</item>
<item name="class" xsi:type="string">manage</item>
<item name="url" xsi:type="string">*/*/</item>
</item>
<item name="save" xsi:type="array">
<item name="name" xsi:type="string">save</item>
<item name="label" xsi:type="string" translate="true">save</item>
<item name="class" xsi:type="string">primary</item>
</item>
</item>
</argument>
Within your top data block, shown above, you have the buttons section. Here your button is defined, note that there is no route defined on it... for some reason you don't need it. Meaning you DO NOT need:
<item name="url" xsi:type="string">*/*/save</item>
Like the manage button has above it. I'm guessing that the form expects the item named save to fire the submit_url. Whats the submit_url, right, onto that.
Within your datasource:
<dataSource name="educationfiles_edit_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">Augustash\EducationFiles\Model\Upload\DataProvider</argument>
<argument name="name" xsi:type="string">educationfiles_edit_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">entity_id</argument>
<argument name="requestFieldName" xsi:type="string">id</argument>
</argument>
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
<item name="submit_url" path="*/*/save" xsi:type="url" />
</item>
</argument>
</dataSource>
Take note of:
<item name="submit_url" path="*/*/save" xsi:type="url" />
This will cause your save button to fire the defined path.
That solves the problem, for extra credit continue on.
How the hell did I figure this out? This is the most important part. Take note of the js_config definition within our datasource block:
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
<item name="submit_url" path="*/*/save" xsi:type="url" />
</item>
This means that Magento is using 'Magento_Ui/js/form/provider' to process this form block. Where is that file...?
'Magento_Ui' is a core module. It is located where all the core files are within your 'vendor' folder at the web root. Within 'vendor' the directory will be named 'module-[modulename]', because of '_Ui'.
Magento_Ui
vendor/magento/module-ui
Knockout files are within 'view', then the respective area- meaning 'base', 'adminhtml', or 'frontend', then the 'web' directory.
vendor/magento/module-ui/view/[area]
From there the path is 'vendor/magento/module-ui/view/base/web/js/form/provider.js'.
Magento_Ui/js/form/provider
vendor/magento/module-ui/view/base/web/js/form/provider.js
Meaning you have to know knockout files are in 'view/[area]/web', then you can piece together the actual file path.
Within provider.js you can find what Magento is looking for, to give yourself a clue as to why/what you are defining in your xml. In this case:
defaults: {
clientConfig: {
urls: {
save: '${ $.submit_url }',
beforeSave: '${ $.validate_url }'
}
}
},
This tells us that provider.js save is looking for a 'submit_url' definition. Which means the 'name' of an xml definition should be that, in our case:
<item name="submit_url" path="*/*/save" xsi:type="url" />
The astute among you will realize that this means we can also define a validation url with 'validate_url'. I haven't tested that... we probly shouldn't assume that it works- but its intended to work, lol. Magento.
Then we know this is javascript, so we can guess that this definition should be set within the 'js_config':
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
<item name="submit_url" path="*/*/save" xsi:type="url" />
</item>
</argument>
In total, our form data and datasource xml:
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">educationfiles_edit.educationfiles_edit_data_source</item>
<item name="deps" xsi:type="string">educationfiles_edit.educationfiles_edit_data_source</item>
</item>
<item name="layout" xsi:type="array">
<item name="type" xsi:type="string">tabs</item>
</item>
<item name="buttons" xsi:type="array">
<item name="manage" xsi:type="array">
<item name="name" xsi:type="string">manage</item>
<item name="label" xsi:type="string" translate="true">Manage</item>
<item name="class" xsi:type="string">manage</item>
<item name="url" xsi:type="string">*/*/</item>
</item>
<item name="save" xsi:type="array">
<item name="name" xsi:type="string">save</item>
<item name="label" xsi:type="string" translate="true">save</item>
<item name="class" xsi:type="string">primary</item>
</item>
</item>
</argument>
<dataSource name="educationfiles_edit_data_source">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">Augustash\EducationFiles\Model\Upload\DataProvider</argument>
<argument name="name" xsi:type="string">educationfiles_edit_data_source</argument>
<argument name="primaryFieldName" xsi:type="string">entity_id</argument>
<argument name="requestFieldName" xsi:type="string">id</argument>
</argument>
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
<item name="submit_url" path="*/*/save" xsi:type="url" />
</item>
</argument>
</dataSource>
Obviously you'll have to replace various details within this code for it to work.
-
Wow thank you for your very detailed answer that goes far beyond the usual "trust me and copy/paste that random piece of code".bfontaine– bfontaine2021年04月20日 09:39:22 +00:00Commented Apr 20, 2021 at 9:39
-
Underrated reply. Thank you man, this fixed my Issue. I had the "suubmit_url" thing in my XML and it didn't work. But I had that in the "config" array, instead of the "js_config" array.Zankar– Zankar2023年10月06日 11:09:16 +00:00Commented Oct 6, 2023 at 11:09
-
Wow, 7 years later and this is still useful. I'm not sure thats a good thing, haha!KazaJhodo– KazaJhodo2023年10月07日 16:47:42 +00:00Commented Oct 7, 2023 at 16:47
first remove this part in xml you have write every button block. you can see vendor/magento/module-cms/view/adminhtml/ui_component/cms_block_form.xml
<item name="update" xsi:type="array">
<item name="name" xsi:type="string">update</item>
<item name="label" xsi:type="string">Save Settings</item>
<item name="class" xsi:type="string">primary</item>
<item name="url" xsi:type="string">*/*/save</item>
</item>
second you block should extend with
class Save extends GenericButton implements ButtonProviderInterface
in dataSource you have to add submit url
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="submit_url" xsi:type="url" path="test/test/save"/>
</item>
-
Yes my button implements ButtonProviderInterface but not extends GenericButton must I create any? In
vendor/magento/module-cms/I saw the request is supported with redirect in controller. It isn't ajax request?Radek Radzik– Radek Radzik2016年10月06日 09:49:15 +00:00Commented Oct 6, 2016 at 9:49 -
yes you have to extends and after your are redirect too
save controller.Qaisar Satti– Qaisar Satti2016年10月06日 10:00:12 +00:00Commented Oct 6, 2016 at 10:00 -
Still same problem undefined at the end of url ... location.href in button with adress index/index (non-existent controller) How magento know to proceed methods in GenericButton? I'm still not redirected to save controllerRadek Radzik– Radek Radzik2016年10月06日 10:23:24 +00:00Commented Oct 6, 2016 at 10:23
-
i didn't change the url after pressing the it's redirect to save. it always show the current page url it is not a error.Qaisar Satti– Qaisar Satti2016年10月06日 10:41:11 +00:00Commented Oct 6, 2016 at 10:41
-
index/index it isn't actual page(controller) even. So should be settings/index? I'm curious mostly why it ads "/undefinded" after reload page. What magento is looking for? What should I configure further.Radek Radzik– Radek Radzik2016年10月06日 10:55:34 +00:00Commented Oct 6, 2016 at 10:55
Add to SaveButton.php return data:
'on_click' => ''
and to settings_form.xml:
<argument name="dataProvider" xsi:type="configurableObject">
...
// Other Child nodes
...
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="submit_url" xsi:type="url" path="path/to/controller/save"/>
</item>
</argument>
</argument>
-
This is the most relevant answer. I would flag it as accepted.zhartaunik– zhartaunik2022年04月12日 18:16:49 +00:00Commented Apr 12, 2022 at 18:16
Step-1: Create Generic.php at app/code/VendoreName/ModuleName/Block/Adminhtml/Edit/Button
<?php
namespace VendoreName\ModuleName\Block\Adminhtml\Edit\Button;
use Magento\Backend\Block\Widget\Context;
use Magento\Cms\Api\PageRepositoryInterface;
class Generic
{
protected $context;
protected $pageRepository;
public function __construct(
Context $context,
PageRepositoryInterface $pageRepository
) {
$this->context = $context;
$this->pageRepository = $pageRepository;
}
public function getUrl($route = '', $params = [])
{
return $this->context->getUrlBuilder()->getUrl($route, $params);
}
}
Step-2: Create Save.php at app/code/VendoreName/ModuleName/Block/Adminhtml/Edit/Button
<?php
namespace VendoreName\ModuleName\Block\Adminhtml\Edit\Button;
use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface;
use Magento\Ui\Component\Control\Container;
class Save extends Generic implements ButtonProviderInterface
{
public function getButtonData()
{
return [
'label' => __('Save'),
'class' => 'save primary',
'data_attribute' => [
'mage-init' => [
'buttonAdapter' => [
'actions' => [
[
'targetName' => 'your_form_ui_component_name.your_form_ui_component_name',
'actionName' => 'save',
'params' => [
false,
],
],
],
],
],
],
];
}
}
Step-3: In your Form Ui-Component file at app/code/VendoreName/ModuleName/view/adminhtml/ui_component add below code:
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<argument name="data" xsi:type="array">
............................................................................................................
<item name="buttons" xsi:type="array">
<item name="save" xsi:type="string">VendoreName\ModuleName\Block\Adminhtml\Edit\Button\Save</item>
</item>
............................................................................................................
</argument>
<dataSource name="your_form_data_source_name">
<argument name="dataProvider" xsi:type="configurableObject">
<argument name="class" xsi:type="string">VendoreName\ModuleName\Model\DataProvider</argument>
<argument name="name" xsi:type="string">your_form_data_source_name</argument>
<argument name="primaryFieldName" xsi:type="string">id</argument>
<argument name="requestFieldName" xsi:type="string">id</argument>
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="submit_url" xsi:type="url" path="*/*/save"/>
</item>
</argument>
</argument>
<argument name="data" xsi:type="array">
<item name="js_config" xsi:type="array">
<item name="component" xsi:type="string">Magento_Ui/js/form/provider</item>
</item>
</argument>
</dataSource>
................................................................................................................
</form>
After adding above files run below command:
php bin/magento s:up
php bin/magento c:c
I also encountered a similar problem. After a lot of trial and error what helped me is to shorten the names of the provider and to get rid of redundant underscore (not sure which one of them helped). In your case, I would suggest changing
settings_form.correctemail_settings_form_data_source to settings_form.correctemailsettings_form_data_source
if that doesn't help, try shortening it to something like settings_form.cesettings_form_data_source
Hope that I helped somebody.
I was too facing the issue that despite doing everything as per core still my save button wasn't working.
While googling I found this link : https://www.pierrefay.com/magento2-training/form-component-backend-crud-admin.html
And when I did exactly like this page told me. The save button worked.