Flash Tip: Fixing broken buttons in Prestashop 1.6’s back office
Many Prestashop 1.6 modules have broken buttons in the back office. Let’s see how to fix them, and apply one of the procedures to the CMS Block Module!
The CMS block ‘New Block’ example
We will use the broken CMS Block back office as guinea pig for this quick tip. If you access its back office (modules -> CMS Block -> click configure) Nothing is going to happen. Same for the cancel button.
Here are the troublesome lines, taken from blockcms.php
$this->fields_form[0]['form'] = array(
'legend' => array(
'title' => $this->l('CMS block configuration'),
'icon' => 'icon-list-alt'
),
'input' => array(
array(
'type' => 'cms_blocks',
'label' => $this->l('CMS Blocks'),
'name' => 'cms_blocks',
'values' => array(
0 => BlockCMSModel::getCMSBlocksByLocation(BlockCMSModel::LEFT_COLUMN, Shop::getContextShopID()),
1 => BlockCMSModel::getCMSBlocksByLocation(BlockCMSModel::RIGHT_COLUMN, Shop::getContextShopID()))
)
),
'buttons' => array(
'newBlock' => array(
'title' => $this->l('New block'),
'href' => $current_index.'&configure='.$this->name.'&token='.$token.'&addBlockCMS',
'class' => 'pull-right',
'icon' => 'process-icon-new'
)
)
);
As you can see, for some reason this module is using href on a button element. Which is simply insane, as a button doesn’t have an href property! How to overcome this? Let’s have a look at *adminfolder*\themes\default\template\helpers\form\form.tpl, which is the default template used to generate a new form with the helper class:
{if isset($fieldset['form']['buttons'])}
{foreach from=$fieldset['form']['buttons'] item=btn key=k}
<button type="{if isset($btn['type'])}{$btn['type']}{else}button{/if}" {if isset($btn['id'])}id="{$btn['id']}"{/if} class="btn btn-default{if isset($btn['class'])} {$btn['class']}{/if}" name="{if isset($btn['name'])}{$btn['name']}{else}submitOptions{$table}{/if}"{if isset($btn.js) && $btn.js} onclick="{$btn.js}"{/if}>{if isset($btn['icon'])}<i class="{$btn['icon']}" ></i> {/if}{$btn.title}</button>
{/foreach}
{/if}
See? No href, obviously. What to do then? Why not using that js attribute? That would do the trick. Back to the php file, change the href to the following, or simply add it afterwards:
'js' => 'javascript: window.location.href = \''.$current_index.'&configure='.$this->name.'&token='.$token.'&addBlockCMS\'',
The array after the change is applied (I replaced the href):
$this->fields_form[0]['form'] = array(
'legend' => array(
'title' => $this->l('CMS block configuration'),
'icon' => 'icon-list-alt'
),
'input' => array(
array(
'type' => 'cms_blocks',
'label' => $this->l('CMS Blocks'),
'name' => 'cms_blocks',
'values' => array(
0 => BlockCMSModel::getCMSBlocksByLocation(BlockCMSModel::LEFT_COLUMN, Shop::getContextShopID()),
1 => BlockCMSModel::getCMSBlocksByLocation(BlockCMSModel::RIGHT_COLUMN, Shop::getContextShopID()))
)
),
'buttons' => array(
'newBlock' => array(
'title' => $this->l('New block'),
'js' => 'javascript: window.location.href = \''.$current_index.'&configure='.$this->name.'&token='.$token.'&addBlockCMS\'',
'class' => 'pull-right',
'icon' => 'process-icon-new'
)
)
);
Save and refresh, it works!
Next up: cancel buttons
The same module has a broken ‘cancel’ button when you try to edit a block. Not such a big deal, but let’s see how to fix it as well! Locate:
'cancelBlock' => array(
'title' => $this->l('Cancel'),
'href' => $back,
'icon' => 'process-icon-cancel'
)
And change it to:
'cancelBlock' => array(
'title' => $this->l('Cancel'),
'js' => 'javascript: window.location.href = \'' . $back .'\'',
'icon' => 'process-icon-cancel'
)
…and all other broken buttons? An alternative
Do we have to change every single occurrence of that broken button? Yes, indeed. Is there an alternative way? Of course, but this means no other associated javascript will work. Instead of editing the php file as we did, open *adminfolder*\themes\default\template\helpers\form\form.tpl directly. Once more, locate:
{if isset($fieldset['form']['buttons'])}
{foreach from=$fieldset['form']['buttons'] item=btn key=k}
<button type="{if isset($btn['type'])}{$btn['type']}{else}button{/if}" {if isset($btn['id'])}id="{$btn['id']}"{/if} class="btn btn-default{if isset($btn['class'])} {$btn['class']}{/if}" name="{if isset($btn['name'])}{$btn['name']}{else}submitOptions{$table}{/if}"{if isset($btn.js) && $btn.js} onclick="{$btn.js}"{/if}>{if isset($btn['icon'])}<i class="{$btn['icon']}" ></i> {/if}{$btn.title}</button>
{/foreach}
{/if}
And change it to
{if isset($fieldset['form']['buttons'])}
{foreach from=$fieldset['form']['buttons'] item=btn key=k}
<button type="{if isset($btn['type'])}{$btn['type']}{else}button{/if}" {if isset($btn['id'])}id="{$btn['id']}"{/if} class="btn btn-default{if isset($btn['class'])} {$btn['class']}{/if}" name="{if isset($btn['name'])}{$btn['name']}{else}submitOptions{$table}{/if}"{if isset($btn.js) && $btn.js} onclick="{$btn.js}"{/if} {if isset($btn.href) && $btn.href} onclick="javascript: window.location.href = '{$btn.href}'"{/if}>{if isset($btn['icon'])}<i class="{$btn['icon']}" ></i> {/if}{$btn.title}</button>
{/foreach}
{/if}
What did we do? We added
{if isset($btn.href) && $btn.href} onclick="javascript: window.location.href = '{$btn.href}'"{/if}
So that any href is automatically turned into an onclick event.
Conclusion
Both ways have their own disadvantage, the first being having to change every single instance of that button’s href, the latter the fact that you might as well need other javascript to be triggered. Which one you choose highly depends on your store’s needs and installed modules!
