Keeping with UI Component form theme but drawing a wider circle, if you take a look at HTML source of a button on a backend Magento 2 HTML form, you’ll see something like the following
<button id="back"
title="Back"
type="button"
class="action- scalable back"
onclick="location.href = 'http://magento-2-1-3.dev/admin/cms/page/index/key/b202205a440f39f9cefe4724da28f8a6b1fa8b255f758f077cd9e8ef3181ca13/';"
data-ui-id="back-button">
<button id="save"
title="Save Page"
type="button"
class="action- scalable save primary ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
onclick="location.href = 'http://magento-2-1-3.dev/admin/cms/index/index/key/d82f1d2820123cf3f9144c3f42ce6cbd3ab129d72ff68b9219fd66fc98544c96/';"
data-form-role="save"
data-ui-id="save-button"
role="button"
aria-disabled="false">
These buttons were not things a front-end developer hand crafted. A PHP class (several, actually) generated this HTML. You may object to this on principle, but that’s not the problem we’re talking about today.
You’ll also notice these buttons have old school onclick
attributes. You may objects to this on principle, but that’s not the problem we’re talking about today.
The problem is, someone created an abstraction for simple buttons. i.e. they wrote some PHP code that generates HTML. Part of this code looks something like this
class BackButton extends GenericButton implements ButtonProviderInterface
{
/**
* @return array
*/
public function getButtonData()
{
return [
'label' => __('Back'),
'on_click' => sprintf("location.href = '%s';", $this->getBackUrl()),
'class' => 'back',
'sort_order' => 10
];
}
/**
* Get URL for back (reset) button
*
* @return string
*/
public function getBackUrl()
{
return $this->getUrl('*/*/');
}
}
A structured array of data provides a label, an onclick
string, an HTML class, and a sort order. This data gets used by the PHP code that renders buttons. Now anyone can create a button that, when clicked on, will go to a URL.
The problem with this is folks who
- Don’t know what these button class are for
- Don’t understand the underlying implementation of the abstraction
If we look back at the HTML source of a button on a form page we see two buttons.
<button id="back"
title="Back"
type="button"
class="action- scalable back"
onclick="location.href = 'http://magento-2-1-3.dev/admin/cms/page/index/key/b202205a440f39f9cefe4724da28f8a6b1fa8b255f758f077cd9e8ef3181ca13/';"
data-ui-id="back-button">
<button id="save"
title="Save Page"
type="button"
class="action- scalable save primary ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
onclick="location.href = 'http://magento-2-1-3.dev/admin/cms/index/index/key/d82f1d2820123cf3f9144c3f42ce6cbd3ab129d72ff68b9219fd66fc98544c96/';"
data-form-role="save"
data-ui-id="save-button"
role="button"
aria-disabled="false">
However, the onclick
attribute is only used on one of these buttons. Click the back button, and the UI will bring you back to the grid listing page by invoking the window.location
javascript. However, the save page button works by POSTing values to a URL (as discussed last time). The location.href
code is ignored. However, it’s left in the HTML source as a red herring for anyone coming along later.
This is a problem you’ll see time and time again when traditional OO patterns are applied to generating user interfaces on the web. Developer A writes a foo abstraction. Developer B needs a foo, so uses that abstraction without fully understanding its guts. Developer’s B’s code “works”, but under the hood it’s a mess.
A front-end developer will look at this situation and think the OO folks are nuts. What’s interesting is, the OO folks probably thinks this is a strength of their systems – i.e. allowing developers to create UIs via PHP and XML without the need to understand any front-end code.