Liste der Anhänge anzeigen (Anzahl: 2)
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:
Anhang 28380
Anhang 28381
So habe ich es auch in der Erweiterung Contao-Custom-Backend-Settings umgesetzt:
https://github.com/heimseiten/contao...ettings-bundle