Contao-Camp 2024
Ergebnis 1 bis 3 von 3

Thema: [irgendwie gelöst] DCA-Filter individuell sortieren

  1. #1
    Contao-Nutzer Avatar von chatjack
    Registriert seit
    02.09.2012.
    Ort
    Essen
    Beiträge
    160

    Standard [irgendwie gelöst] DCA-Filter individuell sortieren

    Hallo zusammen,

    gibt es in Contao eigentlich eine Möglichkeit, einen DCA-Filter individuell zu sortieren?

    Für gewöhnlich sortiert Contao das Select-Feld ja anhand des foreignKey alphabetisch, was auch in den meisten Fällen passt. In diesem Falle würde ich gerne nach Datum sortieren, ohne mit "2021-08-25" beginnen zu müssen.

    screenshot.JPG

    Lieben Gruß
    Dennis
    Geändert von chatjack (26.08.2021 um 14:56 Uhr)

  2. #2
    Contao-Nutzer Avatar von chatjack
    Registriert seit
    02.09.2012.
    Ort
    Essen
    Beiträge
    160

    Standard

    Genauer gesagt geht es um eine Liste von Events, die aus der Tabelle "tl_calendar_events" kommen.

    tl_calendar_tickets.php
    PHP-Code:
    ...
    'fields' => [
        ...
        
    'event' => [
            
    'inputType'     => 'select',
            
    'filter'        => true,
            
    'eval'          => ['mandatory'=>true'chosen'=>true'includeBlankOption'=>true'tl_class'=>'w50''findInSet'=>true],
            
    'sql'           => "int(10) unsigned NOT NULL default '0'",
            
    'foreignKey'    => "tl_calendar_events.CONCAT(title, DATE_FORMAT(FROM_UNIXTIME(startTime), CHAR(32, 40, 37, 100, 46, 37, 109, 46, 37, 89, 41)))"
        
    ],
        ...
    ],
    ... 
    In der tl_calendar_events.php wurde auch ein Feld für die Sortierung angegeben, welches aber im Falle des Filters ignoriert wird.

    PHP-Code:
    ...
        
    'list' => array
        (
            
    'sorting' => array
            (
                ...
                
    'fields'                  => array('startTime'),
                ...
            ),
    ... 

  3. #3
    Contao-Nutzer Avatar von chatjack
    Registriert seit
    02.09.2012.
    Ort
    Essen
    Beiträge
    160

    Standard

    Ich habe es jetzt hinbekommen, wenn auch extrem umständlich.

    Über den Callback list-sorting-panel-callback-subpanel habe ich mir jetzt eigene Select-Felder gebaut, die wie die klassischen Filter die ausgewählten Werte in die Session schreiben.

    PHP-Code:
    <?php

    // src\EventListener\DataContainer\TicketsPanelCallbackListener.php

    namespace BohnMedia\TicketToolBundle\EventListener\DataContainer;

    use 
    Contao\CoreBundle\ServiceAnnotation\Callback;
    use 
    Contao\DataContainer;
    use 
    Doctrine\DBAL\Connection;
    use 
    Symfony\Component\HttpFoundation\RequestStack;
    use 
    Symfony\Component\HttpFoundation\Session\SessionInterface;

    /**
     * @Callback(table="tl_calendar_tickets", target="list.sorting.panel_callback.customfilter")
     */
    class TicketsPanelCallbackListener
    {
        private 
    $request;
        private 
    $conn;
        private 
    $sessionBag;
            
        public function 
    __construct(RequestStack $requestStackConnection $connSessionInterface $session)
        {
            
    $this->request $requestStack->getMainRequest();
            
    $this->conn $conn;
            
    $this->sessionBag $session->getBag('contao_backend');
        }
        
        private function 
    createSelect($field$table$selectfield$order$label$dc)
        {
            
    // Read selected option from post
            
    $active $this->request->get($field);
            
            
    // Get session
            
    $session $this->sessionBag->all();
            
            
    // Update session
            
    if ($active) {
                if (
    $active !== 'tl_' $field) {
                    
    $session['filter'][$dc->table][$field] = $active;
                } else {
                    unset(
    $session['filter'][$dc->table][$field]);
                }
                
    $this->sessionBag->replace($session);
            }
                        
            
    // Get active from session
            
    if (isset($session['filter'][$dc->table][$field])) {
                
    $active $session['filter'][$dc->table][$field];
            }
            
            
    // Build query
            
    $query 'SELECT id, ' $selectfield ' FROM ' $table ' ORDER BY ' $order;
            
            
    // Open select tag
            
    $select '<select name="' $field '" id="' $field '" class="tl_select' . ($active ' active' '') . '">';
            
            
    // Add default options
            
    $select .= '<option value="tl_' $field '">' $label '</option>';
            
    $select .= '<option value="tl_' $field '">---</option>';
            
            
    // Fetch options from database
            
    $stmt $this->conn->query($query);
            while ((
    $row $stmt->fetchNumeric()) !== false)
            {
                
    // Add option from row
                
    $select .= '<option value="' $row[0] . '"' . (($active == $row[0]) ? ' selected' '') .'>' htmlspecialchars($row[1]) . '</option>';
            }
            
            
    // Close select tag
            
    $select .= '</select>';
            
            return 
    $select;
        }
        
        public function 
    __invoke(DataContainer $dc): string
        
    {
            
    $select '';
            
            
    // Event select
            
    $select .= $this->createSelect(
                
    'event',
                
    'tl_calendar_events',
                
    'CONCAT(title, DATE_FORMAT(FROM_UNIXTIME(startTime), CHAR(32, 91, 37, 100, 46, 37, 109, 46, 37, 89, 93)))',
                
    'startTime DESC',
                
    $GLOBALS['TL_LANG']['tl_calendar_tickets']['event'][0],
                
    $dc
            
    );
            
            
    // Member select
            
    $select .= $this->createSelect(
                
    'member',
                
    'tl_member',
                
    'CONCAT(lastname, ", ", firstname)',
                
    'lastname ASC, firstname ASC',
                
    $GLOBALS['TL_LANG']['tl_calendar_tickets']['member'][0],
                
    $dc
            
    );

            return 
    '<div class="tl_filter tl_subpanel"><strong>' $GLOBALS['TL_LANG']['MSC']['filter'] . ':</strong>' $select '</div>';
        }
    }
    Über den Callback config.onload werden die Werte aus der Session dann als Filter im DCA angefügt.

    PHP-Code:
    <?php

    // src\EventListener\DataContainer\TicketsOnloadCallbackListener.php

    namespace BohnMedia\TicketToolBundle\EventListener\DataContainer;

    use 
    Contao\CoreBundle\ServiceAnnotation\Callback;
    use 
    Contao\DataContainer;
    use 
    Symfony\Component\HttpFoundation\Session\SessionInterface;

    /**
     * @Callback(table="tl_calendar_tickets", target="config.onload")
     */
    class TicketsOnloadCallbackListener
    {
        private 
    $sessionBag;

        public function 
    __construct(SessionInterface $session)
        {
            
    $this->sessionBag $session->getBag('contao_backend');
        }

        public function 
    __invoke(DataContainer $dc null): void
        
    {
            
    $filter = [];
            
            
    // Get session data
            
    $session $this->sessionBag->all();
            
            
    // Look for event and member filter in session
            
    foreach (['event''member'] as $field) {
                if (isset(
    $session['filter']['tl_calendar_tickets'][$field])) {
                    
                    
    // Set filter for field in dca
                    
    $value $session['filter']['tl_calendar_tickets'][$field];
                    
    $filter[] = [$field '=?'$value];
                }
            }
            
            
    // Overwrite dca filter
            
    $GLOBALS['TL_DCA']['tl_calendar_tickets']['list']['sorting']['filter'] = $filter;
        }
    }
    Die Klassen wurden wie folgt der services.yml hinzugefügt.

    Code:
    services:
        BohnMedia\TicketToolBundle\EventListener\DataContainer\TicketsPanelCallbackListener:
            arguments: ['@request_stack', '@database_connection', '@session']
    
        BohnMedia\TicketToolBundle\EventListener\DataContainer\TicketsOnloadCallbackListener:
            arguments: ['@session']
    Leider ist die Lösung nur bedingt updatesicher. Falls jemand eine einfachere Lösung kennt, Filter nach einem bestimmten Feld zu sortieren, bin ich weiterhin für jeden Tipp dankbar.

Aktive Benutzer

Aktive Benutzer

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

Lesezeichen

Lesezeichen

Berechtigungen

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