Ajouter une classe à une cellule de tableau Drupal contenant ['données']

11

Dans Drupal 8, le rendu des tableaux ressemble beaucoup à Drupal 7. Vous construisez des tableaux multidimensionnels de lignes et de colonnes en PHP que Drupal transforme respectivement en a <tr>et en <td>s. Il existe toujours ce drupalisme déroutant connu sous le nom 'data'qui vous permet d'ajouter des éléments de tableau de rendu en tant que données de cellule (à ne pas confondre avec les attributs de données).

On m'a donné un site où le développeur a choisi d'utiliser des «données» pour afficher le contenu de la cellule, mais je ne peux pas comprendre comment ajouter une classe aux <td>alentours des données.

J'ai lu le code source et la documentation de Table.php et je suis au courant du nouveau #wrapper_attributes mais je ne peux pas le casser.

J'ai essayé au moins quatre façons d'ajouter la classe, et aucune ne fonctionne.

$table['row-' . $row_id] = [

  // Option 1: Class appears on <tr> tag
  '#attributes' => [
    'class' => ['option-1-row-attributes'],
    'id' => 'row-' . $row_id,
    'no_striping' => TRUE,
  ],

  // Option 2: Class appears on <td> tag of first column. 
  'item' => [
    '#markup' => $row['my_item']->label(),
    '#wrapper_attributes' => [   
      'class' => ['option-2-markup-wrapper-attributes'],
    ],
  ],

  // In the following section, the only item that works is
  // the class on the <a> tag.
  'edit_operation' => [
    'data' => [
      '#type' => 'link',
      '#url' => Url::fromRoute('my_module.my_route', ['item' => $row_id]),
      '#title' => $this->t('Edit'),
      '#attributes' => [
        // Option 3: Class appears on the anchor tag
        'class' => ['use-ajax', 'option-3-link-attributes'],
        'data-dialog-type' => 'modal',
        'data-dialog-options' => Json::encode([
          'width' => 700,
        ]),
      ],
      // Option 4: Has no effect.
      '#wrapper_attributes' => [
        'class' => ['option-4-data-wrapper-attributes'],
      ],
    ],
    // Option 5: Update: This appears to be the correct solution! 
    // Class appears on the <td>.
    '#wrapper_attributes' => [
      'class' => ['option-5-wrapper-attributes'],
    ],
    // Option 6: Has no effect.
    '#attributes' => [
      'class' => ['option-6-attributes'],
    ],
    // Option 7: Has no effect.
    'class' => ['option-7-attributes'],
  ],
];
JamesWilson
la source

Réponses:

12

Après avoir écrit la question en termes généraux, je suis retourné à nouveau pour tester et j'ai déterminé que l'option 5 dans l'OP avec '#wrapper_attributes'au même niveau de l' 'data'élément fonctionne. Je crois que Drupal 8 mettait agressivement en cache la table, parce que mes modifications n'apparaissaient pas même après a drush cr.

Les règles pour ajouter des classes aux tables via PHP backend sont les suivantes:

  • La classe de table requiert #attributes.
  • La classe de ligne TR à l'intérieur de TBODY nécessite #attributes.
  • La classe de cellules TD à l'intérieur de TBODY nécessite #wrapper_attributes.
  • La classe de ligne TR à l'intérieur de THEAD / TFOOT requiert 'class'et des 'data'conteneurs.
    Ni travailler #attributesni #wrapper_attributestravailler ici.
  • La classe de cellules TH / TD à l'intérieur de THEAD / TFOOT requiert 'class'et des 'data'conteneurs.
    Ni travailler #attributesni #wrapper_attributestravailler ici.
  • Il n'y a aucun moyen d'ajouter une classe directement à une balise <thead>ou <tfoot>sans remplacer un modèle de brindille.

Voici l'exemple le plus courant pour ajouter des classes aux balises <tr>& <td>à l'intérieur du main <tbody>, ainsi qu'à la <table>balise principale elle-même:

$table = [
  '#type' => 'table',
  '#attributes' => [
    'class' => ['table-class'],
  ],
  'row1' => [
    '#attributes' => [
      'class' => ['tr-class'],
    ],
    // Table data cell using 'data' for renderable elements.
    'column1' => [
      'data' => [
        '#type' => 'link', // Or any other renderable thing.
        '#attributes' => [
          'class' => ['link-class'],
        ],
        // Other elements required to render the link go here...
      ],
      '#wrapper_attributes' => [ // Watch out!
        'class' => ['td-class'],
      ],
    ],
    // Table data cell using '#markup'.
    'column2' => [
      '#markup' => '<span>' . $this->t('text') . '</span>',
      '#wrapper_attributes' => [   
        'class' => ['td-class'],
      ],
    ],
  ],
];

Notez que le 'class'conteneur accepte une chaîne ou un tableau, mais je suggère de toujours utiliser un tableau.

À partir de là, l'histoire se complique. Si vous devez ajouter des classes aux balises TR ou TD / TH à l'intérieur d'une zone THEAD / TFOOT, les règles changent complètement. Ni travailler #attributesni l' #wrapper_attributesintérieur #headeret les #footersections et essayer de les utiliser ne produisent des effets très étranges.

La structure minimale nue pour les tables avec des colonnes de données d'en-tête / pied de page dans Drupal 8 est la suivante:

$table = [
  '#type' => 'table',
  // Produces <thead> <tr> <th>
  '#header' => [
    'Header 1',
    'Header 2',
    'Header 3',
  ],
  // Produces <tbody> <tr> <td>
  'row1' => [
    'Body 1',
    'Body 2',
    'Body 3',
  ],
  // Produces <tfoot> <tr> <td>
  '#footer' => [
    'Footer 1',
    'Footer 2',
    'Footer 3',
  ],
];

Vous devez modifier la structure réelle des données et introduire deux niveaux de tableaux multidimensionnels supplémentaires, afin de tirer parti de l' 'class'index de tableau qui nécessite également l'introduction de l' 'data'index de tableau. Cela s'applique à la fois à l'élément de ligne et aux éléments de cellule de données, comme le montre l'exemple suivant:

$table = [
  '#type' => 'table',
  // This example works the same way for '#footer'.
  '#header' => [
    // First, introduce an extra level to the array to provide a
    // place to store the class attribute on the <tr> element inside
    // the <thead>.
    [
      'class' => 'thead-tr-class',
      // Next place the columns inside a 'data' container, so that
      // the 'class' can be used.  '#wrapper_attributes' will not
      // work here.
      'data' => [
        // The following line produces data inside a <th>
        // without any class.
        'Header 1',

        // The following lines produce data inside a <th>
        // with a class: th-class.
        [
           'class' => 'th-class',
           'data' => 'Header 2',
           'colspan' => 2
        ],
      ],
    ],
  ],
];

L'exemple d' #headerexemple ci-dessus produit:

<table>
  <thead>
    <tr class="thead-tr-class">
      <th>Header 1</th>
      <th class="th-class" colspan="2">Header 2</th>
    </tr>
  </thead>
</table>
JamesWilson
la source
J'essaie d'utiliser un colspan dans l'en-tête du tableau mais en utilisant votre dernier exemple, j'obtiens ces erreurs:
Adrian Cid Almaguer
Erreur utilisateur: "0" est une clé de tableau de rendu non valide dans Drupal \ Core \ Render \ Element :: children () (ligne 97 de core / lib / Drupal / Core / Render / Element.php). Erreur utilisateur: "classe" est une clé de tableau de rendu non valide dans Drupal \ Core \ Render \ Element :: children () (ligne 97 de core / lib / Drupal / Core / Render / Element.php). Erreur utilisateur: "data" est une clé de tableau de rendu non valide dans Drupal \ Core \ Render \ Element :: children () (ligne 97 de core / lib / Drupal / Core / Render / Element.php). Erreur utilisateur: "colspan" est une clé de tableau de rendu non valide dans Drupal \ Core \ Render \ Element :: children () (ligne 97 de core / lib / Drupal / Core / Render / Element.php).
Adrian Cid Almaguer du
Je viens de trouver une autre solution pour le colspan, jetez un œil ici drupal.stackexchange.com/q/245710/28275
Adrian Cid Almaguer