menatwork / MultiColumnWizard

Contao Extension :: Define unlimited dca fields dynamically
http://contao.org/en/extension-list/view/MultiColumnWizard.html
28 stars 30 forks source link

Backend CSS and JS don't get added when widget isn't loaded #249

Open gmpf opened 6 years ago

gmpf commented 6 years ago

system/modules/multicolumnwizard/html/js/multicolumnwizard_be(_src).js and system/modules/multicolumnwizard/html/css/multicolumnwizard(_src).css are intended to be loaded in the backend no matter whether a MultiColumnWizard widget is loaded or not, for example in case the field is initially hidden because it is part of a subpalette.

However, this doesn't happen because the addition of CSS and JS was rendered ineffectual by https://github.com/menatwork/MultiColumnWizard/pull/213.

The asset paths are added to $GLOBALS['TL_CSS'] and $GLOBALS['TL_JAVASCRIPT'] in a parseTemplate hook: https://github.com/menatwork/MultiColumnWizard/blob/786f2528f3ba345391644b4aeda86096d4957dc9/system/modules/multicolumnwizard/MultiColumnWizardHelper.php#L31-L47 However, that hook is called from Template::parseTemplate after the head tags have already been rendered and added to the template in BackendTemplate::output: https://github.com/contao/core/blob/d883f04807500b5f5c65bf9dd927c38e60812e42/system/modules/core/classes/BackendTemplate.php#L61-L92 Adding anything to those asset arrays in parseTemplate therefore has no effect.

I'm not sure about which way to go in solving this. I can see two approaches at the moment:

  1. The addition of CSS and JS gets moved back to config.php and we detect the install/login pages differently. Something like this (untested):
    
    // config.php
    // …
    $version = VERSION.'.'.BUILD;
    $addBackendAssets = false;
    if (version_compare($version, '4.0', '>='))
    {
    $route = System::getContainer()->get('request_stack')->getCurrentRequest()->get('_route');
    if ($route !== 'contao_install' && $route !== 'contao_backend_login')
    {
        $addBackendAssets = true;
    }
    }
    elseif (TL_SCRIPT !== 'contao/install.php' && TL_SCRIPT !== 'contao/index.php')
    {
    $addBackendAssets = true;
    }

if (TL_MODE == 'BE' && $addBackendAssets) { $GLOBALS['TL_JAVASCRIPT']['mcw'] = $GLOBALS['TL_CONFIG']['debugMode'] ? 'system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js' : 'system/modules/multicolumnwizard/html/js/multicolumnwizard_be.js'; $GLOBALS['TL_CSS']['mcw'] = $GLOBALS['TL_CONFIG']['debugMode'] ? 'system/modules/multicolumnwizard/html/css/multicolumnwizard_src.css' : 'system/modules/multicolumnwizard/html/css/multicolumnwizard.css'; }

_Disadvantages:_ That's quite a few lines of logic for a `config.php`. Also, we'd be using deprecated constants (`VERSION`, `BUILD`), but then again, so does the rest of MCW. ;)

2. Essentially duplicate some of `BackendTemplate::output` to render the head tags and add them to the template after the fact:
```php
// MultiColumnWizardHelper
// …
public function addScriptsAndStyles(&$objTemplate)
{
// …
        $js  = $GLOBALS['TL_CONFIG']['debugMode']
            ? 'system/modules/multicolumnwizard/html/js/multicolumnwizard_be_src.js'
            : 'system/modules/multicolumnwizard/html/js/multicolumnwizard_be.js';
        $css = $GLOBALS['TL_CONFIG']['debugMode']
            ? 'system/modules/multicolumnwizard/html/css/multicolumnwizard_src.css'
            : 'system/modules/multicolumnwizard/html/css/multicolumnwizard.css';
        $objTemplate->javascripts .= \Template::generateScriptTag($js);
        $objTemplate->stylesheets .= \Template::generateStyleTag($css);
// …
}

Disadvantages: Duplication of core code. Also, I think we end up with those tags appearing twice if the widget is loaded as well.

gmpf commented 6 years ago

How to reproduce:

Add this to system/config/dcaconfig.php or app/Resources/contao/dca/tl_page.php:

$GLOBALS['TL_DCA']['tl_page']['subpalettes']['protected'] = 'groups,mcwIssue';

$GLOBALS['TL_DCA']['tl_page']['fields']['mcwIssue'] = [
    'label'     => ['Test MCW issue',''],
    'inputType' => 'multiColumnWizard',
    'eval'      => [
        'columnFields' => [
            'col1'      => [
                'label'            => 'Foo or bar?',
                'inputType'        => 'select',
                'options'          => ['foo', 'bar']
            ],
            'col2' => [
                'label'            => 'Baz or boing?',
                'inputType'        => 'select',
                'options'          => ['baz', 'boing']
            ]
        ]
    ]
];

Edit any regular, non-protected page. If you look at the page source, you can see that the MultiColumnWizard CSS and JS aren't there.

Toggle the protected subpalette by selecting "Protect page" (de: "Seite schützen").

It looks like this in Contao 4.4: 4-4-mcw-without-assets

Contao 3.5: 3-5-mcw-without-assets

When the subpalette-triggering field is already saved as active, the MCW widget is generated and the CSS is loaded:

Contao 4.4 with CSS loaded: 4-4-mcw-with-assets

Contao 3.5: 3-5-mcw-with-assets

(The selects look kind of wrong as well, but that's a different issue.)