Adicionar uma classe a uma célula da tabela Drupal contendo ['data']

11

No Drupal 8, renderizar tabelas ainda é muito parecido com o Drupal 7. Você cria matrizes multidimensionais de linhas e colunas em PHP que o Drupal transforma em a <tr>e <td>s, respectivamente. Ainda existe esse drupalismo confuso conhecido como 'data'que permite adicionar elementos da matriz de renderização como dados da célula (não confunda com os atributos dos dados).

Recebi um site em que o desenvolvedor optou por usar 'dados' para renderizar o conteúdo da célula, mas não consigo descobrir como adicionar uma classe ao <td>redor dos dados.

Eu li o código fonte e a documentação do Table.php e estou ciente do novo, #wrapper_attributes mas não consigo decifrar isso.

Eu tentei pelo menos quatro maneiras de adicionar a classe, e nenhuma funciona.

$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
fonte

Respostas:

12

Depois de escrever a pergunta em termos gerais, voltei a testar novamente e determinei que a Opção 5 no OP com '#wrapper_attributes'o mesmo nível do 'data'elemento funciona. Acredito que o Drupal 8 estava armazenando em cache a tabela de forma agressiva, porque minhas alterações não estavam aparecendo mesmo depois de um drush cr.

As regras para adicionar classes a tabelas via PHP back-end são:

  • A classe da tabela requer #attributes.
  • A classe de linha TR dentro do TBODY requer #attributes.
  • A classe de célula TD dentro do TBODY requer #wrapper_attributes.
  • A classe de linha TR dentro do THEAD / TFOOT requer 'class'e 'data'contêineres.
    Nem #attributesnem #wrapper_attributestrabalhar aqui.
  • A classe de células TH / TD dentro do THEAD / TFOOT requer 'class'e 'data'contêineres.
    Nem #attributesnem #wrapper_attributestrabalhar aqui.
  • Não há como adicionar uma classe diretamente a uma tag <thead>ou <tfoot>sem substituir um modelo de galho.

Aqui está o exemplo mais comum para adicionar classes às tags <tr>& <td>dentro da main <tbody>, bem como à <table>própria tag principal :

$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'],
      ],
    ],
  ],
];

Observe que o 'class'contêiner aceitará uma sequência ou uma matriz, mas sugiro sempre o uso de uma matriz.

A partir daqui, a história fica mais complicada. Se você precisar adicionar classes às tags TR ou TD / TH dentro de uma área THEAD / TFOOT, as regras mudarão completamente. Nem #attributesnem #wrapper_attributesdentro do trabalho #headere #footerseções e tentar usá-los produz efeitos muito estranhos.

A estrutura mínima para tabelas com colunas de dados de cabeçalho / rodapé no Drupal 8 é a seguinte:

$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',
  ],
];

Você deve alterar a estrutura real dos dados e introduzir dois níveis de matrizes multidimensionais adicionais, a fim de alavancar o 'class'índice da matriz, o que exige a introdução também do 'data'índice da matriz. Isso se aplica ao elemento da linha e aos elementos da célula de dados, conforme visto no exemplo a seguir:

$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
        ],
      ],
    ],
  ],
];

O exemplo de #headerexemplo acima produz:

<table>
  <thead>
    <tr class="thead-tr-class">
      <th>Header 1</th>
      <th class="th-class" colspan="2">Header 2</th>
    </tr>
  </thead>
</table>
JamesWilson
fonte
Eu estou tentando usar um colspan no cabeçalho da tabela, mas usando o seu último exemplo, recebo os seguintes erros:
Adrian Cid Almaguer
Erro do usuário: "0" é uma chave de matriz de renderização inválida em Drupal \ Core \ Render \ Element :: children () (linha 97 de core / lib / Drupal / Core / Render / Element.php). Erro do usuário: "class" é uma chave de matriz de renderização inválida em Drupal \ Core \ Render \ Element :: children () (linha 97 de core / lib / Drupal / Core / Render / Element.php). Erro do usuário: "data" é uma chave de matriz de renderização inválida em Drupal \ Core \ Render \ Element :: children () (linha 97 de core / lib / Drupal / Core / Render / Element.php). Erro do usuário: "colspan" é uma chave de matriz de renderização inválida em Drupal \ Core \ Render \ Element :: children () (linha 97 de core / lib / Drupal / Core / Render / Element.php).
Adrian Cid Almaguer
Acabei de encontrar outra solução para o colspan, dê uma olhada aqui drupal.stackexchange.com/q/245710/28275
Adrian Cid Almaguer