65 votes

Sélectionner une ligne en cliquant sur le tableau réactif

J'essaie de trouver la meilleure table à utiliser avec mes applications react, et pour l'instant, la table react-table offre tout ce dont j'ai besoin (pagination, contrôle côté serveur, filtrage, tri, ligne de bas de page).

Ceci étant dit, je ne parviens pas à sélectionner une ligne. Il n'y a pas de exemples qui le montrent.

J'ai notamment essayé de définir un nom de classe lors d'un clic sur la ligne. Mais je n'arrive pas à trouver l'élément d'appel dans le fichier e ni t . De plus, je n'aime pas cette approche, car ce n'est pas la façon dont une application react devrait faire les choses.

<ReactTable
            ...
            getTrProps={(state, rowInfo, column, instance) => {
                return {
                    onClick: (e, t) => {
                        t.srcElement.classList.add('active')
                    },
                    style: {
                    }
                }
            }}
        />

Une solution de rechange possible serait de rendre les cases à cocher en première colonne, mais ce n'est pas optimal car cela limite la zone à cliquer pour "activer" la ligne. En outre, le retour visuel sera moins expressif.

Est-ce que je rate l'éléphant dans la pièce ? Si ce n'est pas le cas, connaissez-vous une autre bibliothèque qui prend en charge les éléments que j'ai décrits précédemment ?

Merci !

EDIT : Une autre option, étant donné qu'il s'agit d'une source ouverte, est de suggérer une modification. Et peut-être que c'est la bonne chose à faire.

EDIT 2

Autre chose, suggérée par Davorin Ruševljan dans les commentaires, mais que je n'ai pas réussi à faire fonctionner :

onRowClick(e, t, rowInfo) {
    this.setState((oldState) => {
        let data = oldState.data.slice();
        let copy = Object.assign({},  data[rowInfo.index]);

        copy.selected = true;
        copy.FirstName = "selected";
        data[rowInfo.index] = copy;

        return {
            data: data,
        }
    })
}

....

            getTrProps={(state, rowInfo, column) => {
                return {
                    onClick: (e, t) => { this.onRowClick(e, t, rowInfo) },
                    style: {
                        background: rowInfo && rowInfo.row.selected ? 'green' : 'red'
                    }
                }
            }}

Ceci définit la colonne 'FirstName' comme 'selected', mais ne définit pas la classe comme 'green'.

78voto

Constantin Guidon Points 1280

J'ai trouvé la solution après quelques essais, j'espère que cela pourra vous aider. Ajoutez ce qui suit à votre <ReactTable> composant :

getTrProps={(state, rowInfo) => {
  if (rowInfo && rowInfo.row) {
    return {
      onClick: (e) => {
        this.setState({
          selected: rowInfo.index
        })
      },
      style: {
        background: rowInfo.index === this.state.selected ? '#00afec' : 'white',
        color: rowInfo.index === this.state.selected ? 'white' : 'black'
      }
    }
  }else{
    return {}
  }
}

Dans votre state n'oubliez pas d'ajouter un null selected valeur, comme :

state = { selected: null }

0 votes

Peut-il faire de la sélection multiple ?

0 votes

Je suppose que vous pouvez le faire mais vous devez implémenter une logique personnalisée pour stocker les index sélectionnés.

5 votes

A fonctionné pour moi aussi, mais j'ai aussi dû vérifier que rowinfo !== undefined pour éviter les erreurs d'exécution

23voto

Alex Points 337

Il y a un HOC inclus pour React-Table qui permet la sélection, même en filtrant et en paginant le tableau, la configuration est légèrement plus avancée que le tableau de base donc lisez d'abord les informations dans le lien ci-dessous.

enter image description here

Après avoir importé le HOC, vous pouvez ensuite l'utiliser comme ceci avec les méthodes nécessaires :

/**
* Toggle a single checkbox for select table
*/
toggleSelection(key: number, shift: string, row: string) {
    // start off with the existing state
    let selection = [...this.state.selection];
    const keyIndex = selection.indexOf(key);

    // check to see if the key exists
    if (keyIndex >= 0) {
        // it does exist so we will remove it using destructing
        selection = [
            ...selection.slice(0, keyIndex),
            ...selection.slice(keyIndex + 1)
        ];
    } else {
        // it does not exist so add it
        selection.push(key);
    }
    // update the state
    this.setState({ selection });
}

/**
* Toggle all checkboxes for select table
*/
toggleAll() {
    const selectAll = !this.state.selectAll;
    const selection = [];

    if (selectAll) {
        // we need to get at the internals of ReactTable
        const wrappedInstance = this.checkboxTable.getWrappedInstance();
        // the 'sortedData' property contains the currently accessible records based on the filter and sort
        const currentRecords = wrappedInstance.getResolvedState().sortedData;
        // we just push all the IDs onto the selection array
        currentRecords.forEach(item => {
            selection.push(item._original._id);
        });
    }
    this.setState({ selectAll, selection });
}

/**
* Whether or not a row is selected for select table
*/
isSelected(key: number) {
    return this.state.selection.includes(key);
}

<CheckboxTable
    ref={r => (this.checkboxTable = r)}
    toggleSelection={this.toggleSelection}
    selectAll={this.state.selectAll}
    toggleAll={this.toggleAll}
    selectType="checkbox"
    isSelected={this.isSelected}
    data={data}
    columns={columns}
/>

Voir ici pour plus d'informations :
https://github.com/tannerlinsley/react-table/tree/v6#selecttable

Voici un exemple concret :
https://codesandbox.io/s/react-table-select-j9jvw

2 votes

Cela semble être la meilleure approche. La sélection est prise en charge par react-table grâce à ce composant d'ordre supérieur.

4voto

Davorin Ruševljan Points 2389

Je ne suis pas familier avec react-table, donc je ne sais pas s'il a un support direct pour la sélection et la désélection (ce serait bien s'il l'avait).

Si ce n'est pas le cas, avec le morceau de code que vous avez déjà, vous pouvez installer le gestionnaire onCLick. Maintenant, au lieu d'essayer d'attacher le style directement à la ligne, vous pouvez modifier l'état, en ajoutant par exemple selected : true aux données de la ligne. Cela déclenchera le rerendu. Il ne vous reste plus qu'à modifier le rendu des lignes avec selected === true. Quelque chose du genre :

// Any Tr element will be green if its (row.age > 20) 
<ReactTable
  getTrProps={(state, rowInfo, column) => {
    return {
      style: {
        background: rowInfo.row.selected ? 'green' : 'red'
      }
    }
  }}
/>

0 votes

Merci pour le replay, @Davorin ! Je ne pense pas que cela sera utile, parce que je n'ai aucun contrôle sur l'état du tableau et donc je ne peux pas définir rowInfo.row.selected.. sans appeler this.setState, le tableau ne se rendra pas à nouveau

0 votes

Comment voulez-vous dire que vous n'avez pas le contrôle, vous fournissez une table avec une propriété de données, vous la changez dans les données.

0 votes

Ce que je voulais dire, c'est que getTrProps ne fait pas partie du rendu de la page, lorsque les données sont modifiées. Et le fait de placer de nouvelles données dans la table ne l'invoque pas, malheureusement. Je vais modifier ma question avec la façon dont j'essaie de le faire.

3voto

Jun Bin Points 64

Si vous voulez avoir une sélection multiple sur la ligne de sélection

import React from 'react';
import ReactTable from 'react-table';
import 'react-table/react-table.css';
import { ReactTableDefaults } from 'react-table';
import matchSorter from 'match-sorter';

class ThreatReportTable extends React.Component{

constructor(props){
  super(props);

  this.state = {
    selected: [],
    row: []
  }
}
render(){

  const columns = this.props.label;

  const data = this.props.data;

  Object.assign(ReactTableDefaults, {
    defaultPageSize: 10,
    pageText: false,
    previousText: '<',
    nextText: '>',
    showPageJump: false,
    showPagination: true,
    defaultSortMethod: (a, b, desc) => {
    return b - a;
  },

  })

    return(
    <ReactTable className='threatReportTable'
        data= {data}
        columns={columns}
        getTrProps={(state, rowInfo, column) => {

        return {
          onClick: (e) => {

            var a = this.state.selected.indexOf(rowInfo.index);

            if (a == -1) {
              // this.setState({selected: array.concat(this.state.selected, [rowInfo.index])});
              this.setState({selected: [...this.state.selected, rowInfo.index]});
              // Pass props to the React component

            }

            var array = this.state.selected;

            if(a != -1){
              array.splice(a, 1);
              this.setState({selected: array});

            }
          },
          // #393740 - Lighter, selected row
          // #302f36 - Darker, not selected row
          style: {background: this.state.selected.indexOf(rowInfo.index) != -1 ? '#393740': '#302f36'},

        }

        }}
        noDataText = "No available threats"
        />

    )
}
}

  export default ThreatReportTable;

0voto

eric gilbertson Points 667

Un autre mécanisme pour le style dynamique consiste à le définir dans le JSX de votre composant. Par exemple, l'élément suivant pourrait être utilisé pour donner un style sélectif à l'étape en cours dans le tutoriel React tic-tac-toe (l'une des améliorations suggérées pour les crédits supplémentaires) :

  return (
    <li key={move}>
      <button style={{fontWeight:(move === this.state.stepNumber ? 'bold' : '')}} onClick={() => this.jumpTo(move)}>{desc}</button>
    </li>
  );

Certes, une approche plus propre consisterait à ajouter/supprimer une classe CSS "sélectionnée", mais cette approche directe peut être utile dans certains cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X