Ergebnis 1 bis 4 von 4

Thema: CSS-Klassen einer Elementgruppe in der "Detailansicht" der Elementgruppe ausgeben

  1. #1
    Contao-Nutzer Avatar von Niels H
    Registriert seit
    14.08.2012.
    Ort
    Köln
    Beiträge
    87
    Partner-ID
    11984

    Standard CSS-Klassen einer Elementgruppe in der "Detailansicht" der Elementgruppe ausgeben

    Es gibt bestimmt einen besseren Weg, aber mit den folgenden Anpassungen können die CSS-Klassen von Elementgruppen in der "Detailansicht" der Elementgruppe ausgegeben werden um bspw. bei Spaltenansichten die Inhaltselemente nebeneinander anzuordnen.

    Es müssen drei Dateien erstellt werden:
    /public_html/contao57.com/src/InsertTag/ElementGroupCssClassInsertTag.php
    /public_html/contao57.com/templates/backend/data_container/table/view/_record_listing.html.twig
    /public_html/contao57.com/templates/backend/data_container/table/view/parent.html.twig

    ElementGroupCssClassInsertTag.php
    HTML-Code:
    <?php
    
    declare(strict_types=1);
    
    namespace App\InsertTag;
    
    use Contao\ContentModel;
    use Contao\CoreBundle\DependencyInjection\Attribute\AsInsertTag;
    use Contao\CoreBundle\Framework\ContaoFramework;
    use Contao\CoreBundle\InsertTag\InsertTagResult;
    use Contao\CoreBundle\InsertTag\OutputType;
    use Contao\CoreBundle\InsertTag\ResolvedInsertTag;
    use Contao\CoreBundle\InsertTag\Resolver\InsertTagResolverNestedResolvedInterface;
    use Contao\StringUtil;
    
    #[AsInsertTag('element_group_cssclass')]
    class ElementGroupCssClassInsertTag implements InsertTagResolverNestedResolvedInterface
    {
        public function __construct(private readonly ContaoFramework $framework) {}
    
        public function __invoke(ResolvedInsertTag $insertTag): InsertTagResult
        {
            $this->framework->initialize();
    
            $id = (int) $insertTag->getParameters()->get(0);
            $model = $this->framework->getAdapter(ContentModel::class)->findByPk($id);
    
            if (!$model || !$model->cssID) {
                return new InsertTagResult('', OutputType::text);
            }
    
            $cssId = StringUtil::deserialize($model->cssID, true);
    
            return new InsertTagResult($cssId[1] ?? '', OutputType::text);
        }
    }
    _record_listing.html.twig
    HTML-Code:
    {% extends '@Contao/backend/data_container/table/view/_record_listing.html.twig' %}
    
    {% set group_css_class = insert_tag('element_group_cssclass::' ~ pid) %}
    {% set listing_attributes = attrs()
        .addClass(group_css_class, group_css_class)
        .mergeWith(listing_attributes|default)
    %}
    parent.html.twig
    HTML-Code:
    {% trans_default_domain 'contao_default' %}
    {% extends '@Contao/backend/data_container/table/view/_base.html.twig' %}
    
    {% set view_attributes = attrs()
        .set('data-controller', 'contao--limit-height', limit_height)
        .set('data-contao--limit-height-max-value', limit_height, limit_height)
        .set('data-contao--limit-height-expand-value', 'MSC.expandNode'|trans, limit_height)
        .set('data-contao--limit-height-collapse-value', 'MSC.collapseNode'|trans, limit_height)
        .set('data-contao--limit-height-expand-all-value', 'DCA.expandNodes.0'|trans, limit_height)
        .set('data-contao--limit-height-expand-all-title-value', 'DCA.expandNodes.1'|trans, limit_height)
        .set('data-contao--limit-height-collapse-all-value', 'DCA.collapseNodes.0'|trans, limit_height)
        .set('data-contao--limit-height-collapse-all-title-value', 'DCA.collapseNodes.1'|trans, limit_height)
    %}
    
    {% block listing %}
        {% if has_clipboard_content %}
            <div id="paste_hint"><p>{{ 'MSC.selectNewPosition'|trans }}</p></div>
        {% endif %}
    
        {% embed '@Contao/backend/data_container/table/view/_record_listing.html.twig' with {
            listing_attributes: attrs().addClass('parent_view').addClass('as-grid', display_grid),
        } %}
            {% trans_default_domain 'contao_default' %}
    
            {% block records %}
                <div class="tl_header hover-div" data-controller="contao--deeplink contao--operations-menu" data-action="contextmenu->contao--operations-menu#open click->contao--check-all#toggleInput">
                    <div class="tl_content_right">
                    
                        {# Hinzufügen von CSS-Klassen - start #}
                        {% set group_css_class = insert_tag('element_group_cssclass::' ~ pid) %}
                        {% if group_css_class %}
                            <span class="cssIdClass">
                                <code class="cssClass">
                                    {% for class in group_css_class|split(' ') %}
                                        {% if class %}
                                            <span>{{ class }}</span>
                                        {% endif %}
                                    {% endfor %}
                                </code>
                            </span>
                        {% endif %}
                        {# Hinzufügen von CSS-Klassen - end #}
                        
                        {{ block('select_all_button') }}
    
                        {{ header_operations|default|raw }}
                    </div>
                    <table class="tl_header_table">
                        {% for label, value in table_headers %}
                            <tr>
                                <td><span class="tl_label">{{ label }}</span></td>
                                <td>{{ value }}</td>
                            </tr>
                        {% endfor %}
                    </table>
                </div>
    
                {% if records|length %}
                    {% set list_attributes = attrs()
                        .set('data-controller', 'contao--sortable', is_sortable)
                        .set('data-contao--sortable-handle-value', '.drag-handle', is_sortable)
                        .set('data-contao--sortable-parent-mode-value', 'true', is_sortable)
                        .set('data-contao--sortable-request-token-value', contao.request_token, is_sortable)
                        .set('data-id', pid, is_sortable)
                    %}
                    <ul{{ list_attributes }}>
                        {% for record in records %}
                            <li{{ attrs().set('data-id', record.id, is_sortable) }}>
                                {% if record.group_header is defined %}
                                    <div class="tl_content_header">{{ record.group_header|raw }}</div>
                                {% endif %}
    
                                {% set record_attributes = attrs()
                                    .addClass('tl_content')
                                    .addClass('wrapper_start', record.display.wrapper_start|default)
                                    .addClass('wrapper_separator', record.display.wrapper_separator|default)
                                    .addClass('wrapper_stop', record.display.wrapper_stop|default)
                                    .addClass(['indent', "indent_#{record.display.wrap_level|default}"], record.display.wrap_level|default)
                                    .addClass('indent_first', record.display.indent_first|default)
                                    .addClass('indent_last', record.display.indent_last|default)
                                    .addClass('draft', record.is_draft)
                                    .addClass(record.class)
                                    .set('data-turbo', 'false')
                                    .set('data-action', 'click->contao--check-all#toggleInput')
                                %}
                                <div{{ record_attributes }}>
                                    <div class="inside hover-div" data-controller="contao--deeplink contao--operations-menu" data-action="contextmenu->contao--operations-menu#open">
                                        {# Right column #}
                                        <div class="tl_content_right" data-turbo="true">
                                            {{ include(('@Contao/backend/data_container/table/view/_record_operations.html.twig')) }}
                                        </div>
    
                                        {# Record #}
                                        {% if record.legacy_data is defined %}
                                            {{ record.legacy_data|raw }}
                                        {% else %}
                                            {% if display_grid %}
                                                {# Record displayed as box with optional preview #}
                                                {% set record_label_attributes = attrs()
                                                    .addClass('cte_type')
                                                    .addClass('draggable', record.allow_dragging)
                                                    .addClass(record.state, record.state)
                                                %}
                                                <div{{ record_label_attributes }}>
                                                    {% block label %}
                                                        {% if record.allow_dragging %}
                                                            <button type="button" class="drag-handle" data-action="keydown->contao--sortable#move">
                                                                {{ backend_icon('drag.svg', record.drag_handle_label) }}
                                                            </button>
                                                            <div>{{ record.label|raw }}</div>
                                                        {% else %}
                                                            {{ record.label|raw }}
                                                        {% endif %}
                                                    {% endblock %}
                                                </div>
    
                                                {% if record.preview %}
                                                    <div class="cte_content" data-contao--limit-height-target="node">
                                                        <div class="cte_preview" style="contain:paint">{{ record.preview|raw }}</div>
                                                    </div>
                                                {% endif %}
                                            {% else %}
                                                {# Record displayed flat #}
                                                {% set record_label_attributes = attrs()
                                                    .addClass('tl_content_left')
                                                    .addClass('draggable', record.allow_dragging)
                                                    .addClass(record.state, record.state)
                                                %}
                                                <div{{ record_label_attributes }}>
                                                    {{ block('label') }}
                                                </div>
                                            {% endif %}
                                        {% endif %}
                                    </div>
                                </div>
                            </li>
                        {% endfor %}
                    </ul>
                {% else %}
                    <p class="tl_empty_parent_view">{{ (panel_active ? 'MSC.noResultWithFilter' : 'MSC.noResult')|trans }}</p>
                {% endif %}
            {% endblock %}
        {% endembed %}
    {% endblock %}
    optionales Backend CSS:
    HTML-Code:
    /* Vorschau der Elementgruppe - Start */
    .cte_preview > :is(.Spalten2, .Spalten3, .Spalten4, .Spalten5, .Spalten6) {
    	& > * {
    		background: var(--content-bg);
    		border: 1px solid var(--border);
    		border-radius: var(--border-radius);
    		padding: 10px;
    	}
    }
    
    .tl_content:has(.Spalten2, .Spalten3, .Spalten4, .Spalten5, .Spalten6) {
    	.cte_preview { background: var(--panel-bg); }
    	[data-contao--limit-height-target][style*=max-height] .limit_toggler {
    		background: linear-gradient(transparent,var(--panel-bg) 60%);
    	}
    }
    /* Vorschau der Elementgruppe - Ende */
    
    /* Operations-Icons ausblenden um Platz zu sparen - Start */
    .Spalten2, .Spalten3, .Spalten4, .Spalten5, .Spalten6 {
    	& > ul .tl_content_right .operations > ul > li {
    		display: none;
    		&:first-child, &:has([data-label="Verstecken"]), &.operations-menu-container { display: block; }
    	}
    }
    /* Operations-Icons ausblenden um Platz zu sparen - Ende */
    
    /* Abstand oben korrigieren - Start */
    .Spalten2, .Spalten3, .Spalten4, .Spalten5, .Spalten6 {
    	.tl_content { margin-top: 0; }
    }
    /* Abstand oben korrigieren - Ende */
    
    .cte_preview :is(.Spalten2, .Spalten3, .Spalten4, .Spalten5, .Spalten6) { gap: 10px; }
    .Spalten2 > ul, .cte_preview .Spalten2,
    .Spalten3 > ul, .cte_preview .Spalten3,
    .Spalten4 > ul, .cte_preview .Spalten4,
    .Spalten5 > ul, .cte_preview .Spalten5,
    .Spalten6 > ul, .cte_preview .Spalten6 { 
    	display: grid;
    	gap: 15px;
    }
    .Spalten2 > ul, .cte_preview .Spalten2 { grid-template-columns: repeat(2, 1fr); }
    .Spalten3 > ul, .cte_preview .Spalten3 { grid-template-columns: repeat(3, 1fr); }
    .Spalten4 > ul, .cte_preview .Spalten4 { grid-template-columns: repeat(4, 1fr); }
    .Spalten5 > ul, .cte_preview .Spalten5 { grid-template-columns: repeat(5, 1fr); }
    .Spalten6 > ul, .cte_preview .Spalten6 { grid-template-columns: repeat(6, 1fr); }
    
    /* Backend Swiper Vorschau - Start */
    .cte_preview .content-custom-swiper .swiper-wrapper {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        gap: 10px;
    }
    
    .cte_preview img:not(.backend-icon) {
    	max-width: 100%;
    }
    /* Backend Swiper Vorschau - Ende */
    
    div[class^='Spalten'], div[class*=' Spalten'] {
    	
    	&.Spalte1Breite10 ul { --ErsteSpalte: 10fr; } &.Spalte1Breite15 ul { --ErsteSpalte: 15fr; } &.Spalte1Breite20 ul { --ErsteSpalte: 20fr; } &.Spalte1Breite25 ul { --ErsteSpalte: 25fr; } &.Spalte1Breite30 ul { --ErsteSpalte: 30fr; } &.Spalte1Breite35 ul { --ErsteSpalte: 35fr; } &.Spalte1Breite40 ul { --ErsteSpalte: 40fr; } &.Spalte1Breite45 ul { --ErsteSpalte: 45fr; } &.Spalte1Breite50 ul { --ErsteSpalte: 50fr; } &.Spalte1Breite55 ul { --ErsteSpalte: 55fr; } &.Spalte1Breite60 ul { --ErsteSpalte: 60fr; } &.Spalte1Breite65 ul { --ErsteSpalte: 65fr; } &.Spalte1Breite70 ul { --ErsteSpalte: 70fr; } &.Spalte1Breite75 ul { --ErsteSpalte: 75fr; } &.Spalte1Breite80 ul { --ErsteSpalte: 80fr; } &.Spalte1Breite85 ul { --ErsteSpalte: 85fr; } &.Spalte1Breite90 ul { --ErsteSpalte: 90fr; } &.Spalte1Breite95 ul { --ErsteSpalte: 95fr; }
    	&.Spalte2Breite10 ul { --ZweiteSpalte: 10fr; } &.Spalte2Breite15 ul { --ZweiteSpalte: 15fr; } &.Spalte2Breite20 ul { --ZweiteSpalte: 20fr; } &.Spalte2Breite25 ul { --ZweiteSpalte: 25fr; } &.Spalte2Breite30 ul { --ZweiteSpalte: 30fr; } &.Spalte2Breite35 ul { --ZweiteSpalte: 35fr; } &.Spalte2Breite40 ul { --ZweiteSpalte: 40fr; } &.Spalte2Breite45 ul { --ZweiteSpalte: 45fr; } &.Spalte2Breite50 ul { --ZweiteSpalte: 50fr; } &.Spalte2Breite55 ul { --ZweiteSpalte: 55fr; } &.Spalte2Breite60 ul { --ZweiteSpalte: 60fr; } &.Spalte2Breite65 ul { --ZweiteSpalte: 65fr; } &.Spalte2Breite70 ul { --ZweiteSpalte: 70fr; } &.Spalte2Breite75 ul { --ZweiteSpalte: 75fr; } &.Spalte2Breite80 ul { --ZweiteSpalte: 80fr; } &.Spalte2Breite85 ul { --ZweiteSpalte: 85fr; } &.Spalte2Breite90 ul { --ZweiteSpalte: 90fr; } &.Spalte2Breite95 ul { --ZweiteSpalte: 95fr; }
    	&.Spalte3Breite10 ul { --DritteSpalte: 10fr; } &.Spalte3Breite15 ul { --DritteSpalte: 15fr; } &.Spalte3Breite20 ul { --DritteSpalte: 20fr; } &.Spalte3Breite25 ul { --DritteSpalte: 25fr; } &.Spalte3Breite30 ul { --DritteSpalte: 30fr; } &.Spalte3Breite35 ul { --DritteSpalte: 35fr; } &.Spalte3Breite40 ul { --DritteSpalte: 40fr; } &.Spalte3Breite45 ul { --DritteSpalte: 45fr; } &.Spalte3Breite50 ul { --DritteSpalte: 50fr; } &.Spalte3Breite55 ul { --DritteSpalte: 55fr; } &.Spalte3Breite60 ul { --DritteSpalte: 60fr; } &.Spalte3Breite65 ul { --DritteSpalte: 65fr; } &.Spalte3Breite70 ul { --DritteSpalte: 70fr; } &.Spalte3Breite75 ul { --DritteSpalte: 75fr; } &.Spalte3Breite80 ul { --DritteSpalte: 80fr; } &.Spalte3Breite85 ul { --DritteSpalte: 85fr; } &.Spalte3Breite90 ul { --DritteSpalte: 90fr; } &.Spalte3Breite95 ul { --DritteSpalte: 95fr; }
    	&.Spalte4Breite10 ul { --VierteSpalte: 10fr; } &.Spalte4Breite15 ul { --VierteSpalte: 15fr; } &.Spalte4Breite20 ul { --VierteSpalte: 20fr; } &.Spalte4Breite25 ul { --VierteSpalte: 25fr; } &.Spalte4Breite30 ul { --VierteSpalte: 30fr; } &.Spalte4Breite35 ul { --VierteSpalte: 35fr; } &.Spalte4Breite40 ul { --VierteSpalte: 40fr; } &.Spalte4Breite45 ul { --VierteSpalte: 45fr; } &.Spalte4Breite50 ul { --VierteSpalte: 50fr; } &.Spalte4Breite55 ul { --VierteSpalte: 55fr; } &.Spalte4Breite60 ul { --VierteSpalte: 60fr; } &.Spalte4Breite65 ul { --VierteSpalte: 65fr; } &.Spalte4Breite70 ul { --VierteSpalte: 70fr; } &.Spalte4Breite75 ul { --VierteSpalte: 75fr; } &.Spalte4Breite80 ul { --VierteSpalte: 80fr; } &.Spalte4Breite85 ul { --VierteSpalte: 85fr; } &.Spalte4Breite90 ul { --VierteSpalte: 90fr; } &.Spalte4Breite95 ul { --VierteSpalte: 95fr; }
    	&.Spalte5Breite10 ul { --FünfteSpalte: 10fr; } &.Spalte5Breite15 ul { --FünfteSpalte: 15fr; } &.Spalte5Breite20 ul { --FünfteSpalte: 20fr; } &.Spalte5Breite25 ul { --FünfteSpalte: 25fr; } &.Spalte5Breite30 ul { --FünfteSpalte: 30fr; } &.Spalte5Breite35 ul { --FünfteSpalte: 35fr; } &.Spalte5Breite40 ul { --FünfteSpalte: 40fr; } &.Spalte5Breite45 ul { --FünfteSpalte: 45fr; } &.Spalte5Breite50 ul { --FünfteSpalte: 50fr; } &.Spalte5Breite55 ul { --FünfteSpalte: 55fr; } &.Spalte5Breite60 ul { --FünfteSpalte: 60fr; } &.Spalte5Breite65 ul { --FünfteSpalte: 65fr; } &.Spalte5Breite70 ul { --FünfteSpalte: 70fr; } &.Spalte5Breite75 ul { --FünfteSpalte: 75fr; } &.Spalte5Breite80 ul { --FünfteSpalte: 80fr; } &.Spalte5Breite85 ul { --FünfteSpalte: 85fr; } &.Spalte5Breite90 ul { --FünfteSpalte: 90fr; } &.Spalte5Breite95 ul { --FünfteSpalte: 95fr; }
    	&.Spalte6Breite10 ul { --SechsteSpalte: 10fr; } &.Spalte6Breite15 ul { --SechsteSpalte: 15fr; } &.Spalte6Breite20 ul { --SechsteSpalte: 20fr; } &.Spalte6Breite25 ul { --SechsteSpalte: 25fr; } &.Spalte6Breite30 ul { --SechsteSpalte: 30fr; } &.Spalte6Breite35 ul { --SechsteSpalte: 35fr; } &.Spalte6Breite40 ul { --SechsteSpalte: 40fr; } &.Spalte6Breite45 ul { --SechsteSpalte: 45fr; } &.Spalte6Breite50 ul { --SechsteSpalte: 50fr; } &.Spalte6Breite55 ul { --SechsteSpalte: 55fr; } &.Spalte6Breite60 ul { --SechsteSpalte: 60fr; } &.Spalte6Breite65 ul { --SechsteSpalte: 65fr; } &.Spalte6Breite70 ul { --SechsteSpalte: 70fr; } &.Spalte6Breite75 ul { --SechsteSpalte: 75fr; } &.Spalte6Breite80 ul { --SechsteSpalte: 80fr; } &.Spalte6Breite85 ul { --SechsteSpalte: 85fr; } &.Spalte6Breite90 ul { --SechsteSpalte: 90fr; } &.Spalte6Breite95 ul { --SechsteSpalte: 95fr; }
    
    	&.Spalten2 ul { grid-template-columns: minmax(var(--Mindestbreite, 200px), var(--ErsteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--ZweiteSpalte, 1fr) ); }
    	&.Spalten3 ul { grid-template-columns: minmax(var(--Mindestbreite, 200px), var(--ErsteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--ZweiteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--DritteSpalte, 1fr) ); }
    	&.Spalten4 ul { grid-template-columns: minmax(var(--Mindestbreite, 200px), var(--ErsteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--ZweiteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--DritteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--VierteSpalte, 1fr) ); }
    	&.Spalten5 ul { grid-template-columns: minmax(var(--Mindestbreite, 200px), var(--ErsteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--ZweiteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--DritteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--VierteSpalte, 1fr) ) minmax(var(--Mindestbreite, 200px), var(--FünfteSpalte, 1fr) ); }
    	&.Spalten6 ul { grid-template-columns: minmax(100px, var(--ErsteSpalte, 1fr) ) minmax(100px, var(--ZweiteSpalte, 1fr) ) minmax(100px, var(--DritteSpalte, 1fr) ) minmax(100px, var(--VierteSpalte, 1fr) ) minmax(100px, var(--FünfteSpalte, 1fr) ) minmax(100px, var(--SechsteSpalte, 1fr) ); }
    
    }

    Danach muss noch der Cache geleert werden.

    Damit können dann, mit eigenem CCS im Backend, folgende Ansichten umgesetzt werden:
    Bildschirmfoto 2026-05-12 um 10.35.55.png
    Bildschirmfoto 2026-05-12 um 10.36.24.png

    So habe ich es auch in der Erweiterung Contao-Custom-Backend-Settings umgesetzt:
    https://github.com/heimseiten/contao...ettings-bundle

  2. #2
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    38.626
    Partner-ID
    10107

    Standard

    Statt dem Insert-Tag solltest du wenn dann eher eine Twig-Funktion nutzen.
    » sponsor me via GitHub or Revolut

  3. #3
    Contao-Urgestein
    Registriert seit
    24.02.2021.
    Beiträge
    2.061
    Contao-Projekt unterstützen

    Support Contao

    Standard

    Zitat Zitat von Spooky Beitrag anzeigen
    Statt dem Insert-Tag solltest du wenn dann eher eine Twig-Funktion nutzen.
    Hab ich hier als Issue geöffnet, hat sich aber nix getan (also Null Antwort), daher hab ich es wieder geschlossen (Ist dann ja wohl nicht geplant)
    https://github.com/heimseiten/contao...undle/issues/1

  4. #4
    Contao-Nutzer Avatar von Niels H
    Registriert seit
    14.08.2012.
    Ort
    Köln
    Beiträge
    87
    Partner-ID
    11984

    Standard

    Danke Spooky. Dass hatte Zoglo auch schon angemerkt. Ich habe es im ersten Schritt nur so geschafft. Wenn ich mich das nächste Mal damit beschäftige, versuche ich eine Lösung ohne insert_tag zu finden.

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 4 (Registrierte Benutzer: 0, Gäste: 4)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •