18

i have the following component with datatables:

import React, { Component } from 'react'
import { Link } from 'react-router'


import { PanelContainer, Panel, PanelBody, Grid, Row, Col } from '@sketchpixy/rubix'

import $ from 'jquery'
import DataTable from 'datatables.net'

$.DataTable = DataTable

const columns = [{
  title: '<input type="checkbox" />',
  data: 'check',
}, {
  title: 'Foto',
  data: 'avatar',
}, {
  title: 'Nombre',
  data: 'name',
}, {
  title: 'Dirección',
  data: 'address',
}, {
  title: 'Clasificación',
  data: 'clasification',
}, {
  title: 'Editar',
  data: 'editLink',
  render: x => `<a href="${x}"><i class="icon-fontello-edit"></i></a>`, // <-- this line i'm interested!
}]

class Table extends Component {
  transform(content) {
    return content.map(x => ({
      ...x,
      check: '<input type="checkbox" />',
      avatar: '<img src="/public/imgs/app/nico.jpg" width="40" height="40" style="border-radius: 100%;">',
      clasification: `<i class="${x.clasification.icon}"></i> ${x.clasification.name}`,
    }))
  }

  componentDidMount(nextProps, nextState) {
    this.table = $(this.refs.main).DataTable({
      dom: '<"data-table-wrapper"tip>',
      data: [],
      columns,
      language: {
        info: 'Mostrando _START_-_END_ de _TOTAL_ puntos',
        infoEmpty: 'No hay puntos',
        paginate: {
          next: 'Siguiente',
          previous: 'Anterior',
        },
      },
    })
  }

  componentWillUpdate() {
    this.table.clear()
    this.table.rows.add(this.transform(this.props.data))
    this.table.draw()
  }

  componentWillUnmount() {
    $('.data-table-wrapper')
    .find('table')
    .DataTable()
    .destroy(true)
  }

  render() {
    return (
        <table
          className="table table-striped hover"
          cellSpacing="0"
          width="100%"
          ref="main"
        />
    )
  }
}

export default p =>
  <PanelContainer>
    <Panel>
      <PanelBody>
        <Grid>
          <Row>
            <Col xs={12}>
              <Table data={p.data} />

            </Col>
          </Row>
        </Grid>
      </PanelBody>
    </Panel>
  </PanelContainer>

The problem is that, with datatables, i need to render a Link with react router, using an anchorlink () is not a solution because it will re-render the whole page. So i need to render a custom component in the column with the specified link. The link is constructed with the ID.

Nico
  • 1,241
  • 1
  • 13
  • 29
  • Up!, in need of an answer :) – Nico May 22 '17 at 14:55
  • Been struggling with this for a while. Were you able to find an answer? – Abhinav Pandey May 24 '17 at 10:44
  • I have same issue with an oppened question for more than two weeks and anybody answer it. :( – JuMoGar May 24 '17 at 10:48
  • 1
    I will post it here. If anyone knows answer, please, help me too. After a log time struggling with this, I have no resolve. https://stackoverflow.com/questions/43927638/ajax-datatables-adding-a-condition-in-columns-render-which-returns-a-but – JuMoGar May 24 '17 at 10:50

3 Answers3

20

I will answer my own question for other developers. What i did is the following:

columnDefs: [{
  targets: 5,
  createdCell: (td, cellData, rowData, row, col) =>
    ReactDOM.render(
      <a style={{ cursor: 'pointer' }}
        onClick={() => this.props.goto(cellData) }>
        <i className="icon-fontello-edit"></i>
      </a>, td),
} // ... the rest of the code

The createdCell method receives the actual dom element, so you can render the react component directly there, the only problem is that you cannot render Links, that is because the router needs a context and that context is lost. So the best way is to use a method to go to the specific route, which in this case goto is this.props.router.push passed from the parent.

Nico
  • 1,241
  • 1
  • 13
  • 29
  • but.. there you are rendering an a, not an Link of react router, right? . Could you put an example more extended? Or pass here, and answer me, please? https://stackoverflow.com/questions/43927638/ajax-datatables-adding-a-condition-in-columns-render-which-returns-a-but . Thank you. – JuMoGar May 27 '17 at 00:47
  • 1
    Link will not work because it needs a context, thats why you need to add an onClick event to handle the routing. – Nico May 29 '17 at 17:17
  • to handle routing easy and without using tag, using react router 4+, you can redirect to others page like that: this.props.history.push({ pathname: '/your_path', state: { id: some_value } }); refer to this for details: https://stackoverflow.com/a/31079244/960326 – Fuong Lee Apr 20 '18 at 03:04
  • @Nico Could you please look into this, not very similar but I am stuck here, and in need a answer: https://stackoverflow.com/questions/53945879/reactjs-could-not-update-state-when-used-with-tabs . Thank you. – Reema Parakh Dec 28 '18 at 05:48
1

Maybe you could utilize ReactDOM.render. The function takes in a component and a container, so you could initialize your links as empty nodes with your props as data-types. Then in componentDidMount, you could loop through and call a function that looks like this: edit: the Link component requires the react context to navigate around implicitly and I don't think reactDOM.render reconciles your context object with the one that it creates. Best bet would be to create a custom link component to use here that uses the browserHistory(react-router v3) or just history library to navigate.

componentDidMount() {
 function populateLinks(node) {
   const linkURL = node.dataset.linkURL;
   reactDOM.render(<Link to={linkURL}>Hello</Link>, node);
  }
$('.link-div').get().forEach(populateLinks);
}

It looks like you would specify a specific dom node to render with something like this:

$('#example').dataTable( {
  "columnDefs": [ {
    "targets": 0,
    "data": "download_link",
    "render": function ( data, type, full, meta ) {
      return `<div class="link-div" data-linkURL=${data}></div>`;
    }
  } ]
} );

Let me know how it goes!

Stephen L
  • 2,273
  • 11
  • 16
  • I have tried it but it is not working. I import ReactDOM too: `import ReactDOM from 'react-dom';` but I get error ReactDom is not defined – JuMoGar May 25 '17 at 17:23
  • Make sure you capitalize reactDOM – Stephen L May 25 '17 at 17:24
  • 1
    Warning: Failed prop type: The prop `to` is marked as required in `Link`, but its value is `undefined`. in Link ------ This is due to is not recognoised href prop – JuMoGar May 25 '17 at 17:33
  • 1
    Warning: Failed context type: The context `router` is marked as required in `Link`, but its value is `undefined`. in Link ------ I do not know why is it – JuMoGar May 25 '17 at 17:34
  • 1
    Uncaught TypeError: Cannot read property 'history' of undefined --- Neither this – JuMoGar May 25 '17 at 17:34
  • what version of react router are you using? – Stephen L May 25 '17 at 17:34
  • 2
    4.1.1. Lastest. Also I add that on your render `ReactDOM.render(HELLO, node);` due to link has a name – JuMoGar May 25 '17 at 17:35
  • Okay. I am only familiar with react-router v3. But it looks like the Link component cannot grab the context required to navigate around. You may have to make your own custom Link component that imports history to programmatically navigate. – Stephen L May 25 '17 at 17:40
  • Ok. I do not know how could do that. I will search information. Thank you for your help!! – JuMoGar May 25 '17 at 17:44
1

use ReactDOMServer to render as string

import ReactDOMServer from 'react-dom/server';
const [select, setSelect] = useState(false);

    render: (data) => ReactDOMServer.renderToString(<input type="checkbox" checked={select} />)
  • Be careful with this one as it will only load the component without registering any event listener. So any `onClick` event won't fire. – Rahul Haque Oct 31 '22 at 20:15