question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Custom Search Toolbar Not Rendering my Custom Element, Uses Default.

See original GitHub issue

Hello!

After trying many react datatables, I have decided that react-bootstrap-table is by far the best design, great work! I’m experiencing some difficulties however. I want to completely modify the table header so it renders a custom themed search bar and tool bar that matches my table styling. Here is a screenshot of the expected end result:

screen shot 2016-12-02 at 10 39 38 am

I’ve been able to theme the table just fine but the code I have written for the header toolbar doesn’t render but no exceptions are thrown by webpack or browser console so I’m not sure what I’m doing wrong or if this is perhaps a bug. Help is much appreciated!

My Table Search class which returns the custom toolbar HTML

class CyhyTableSearch extends React.Component {

  getValue() {
    return ReactDOM.findDOMNode(this).value;
  }

  setValue(value) {
    ReactDOM.findDOMNode(this).value = value;
  }

  render() {
    return (
      <div className="flakes-search">
        <input 
          ref="search-input"
          className="flakes-search"
          placeholder={ this.props.placeholder } 
          defaultValue={ this.props.defaultValue } 
          onKeyUp={ this.props.search } />
        
        <div className="flakes-actions-bar">
          <button 
            className="action button-gray smaller right" 
            defaultValue="Add Value" />
          <button 
            className="action button-gray smaller right" 
            defaultValue="Export CSV" />
        </div>
      </div>
    );
  }
}

And my Table Class:

class CyhyTable extends React.Component {

  csvFormatter(cell, row) {
    return `${row.id}: ${cell} USD`;
  }

  render() {
    const selectRowProp = {
      mode: 'checkbox'
    };

    const options = {
      clearSearch: false,
      searchPanel: (props) => (<CyhyTableSearch { ...props }/>),
      page: 1,  // which page you want to show as default
      sizePerPage: 25,  // which size per page you want to locate as default
      pageStartIndex: 0, // where to start counting the pages
      paginationSize: 3,  // the pagination bar size.
      prePage: 'Prev', // Previous page button text
      nextPage: 'Next', // Next page button text
      firstPage: 'First', // First page button text
      lastPage: 'Last', // Last page button text
      sizePerPageList: [ {
      text: '5', value: 5
      }, {
      text: '10', value: 10
      }, {    
      text: '15', value: 15
      }, {
      text: '25', value: 25
      }, {
      text: '50', value: 50
      }, {
      text: '100', value: 100
      }, {
      text: 'All', value: cyhyData.length
      } ],      
    };

    return (
      <BootstrapTable
        data={ cyhyData }
        options={ options }
        selectRow={ selectRowProp }
        exportCSV={ true }
        pagination={ true }
        tableHeaderClass='flakes-table'
        tableBodyClass='flakes-table'
        containerClass='flakes-table'
        tableContainerClass='flakes-table'
        headerContainerClass='flakes-table'
        bodyContainerClass='flakes-table' 
        search >
    
        <TableHeaderColumn dataField='Facility'>Facility</TableHeaderColumn>
        <TableHeaderColumn dataField='Severity'>Severity</TableHeaderColumn>
        <TableHeaderColumn dataField='DNS'>DNS</TableHeaderColumn>
        <TableHeaderColumn isKey={true} dataField='IP'>IP</TableHeaderColumn>
        <TableHeaderColumn dataField='Port'>Port</TableHeaderColumn>
        <TableHeaderColumn dataField='vulnName'>Vulnerability</TableHeaderColumn>
      </BootstrapTable>
    );
  }
}

And my app.js render method:

ReactDOM.render(
  <CyhyTable />,
    document.getElementById('table')
);

And this is the rendered result:

screen shot 2016-12-02 at 11 08 05 am

Everything is rendered default so it appears.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:14 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
reconSFcommented, Dec 9, 2016

Fantastic! Worked like a charm. Thank you for providing such great dev support!

My only request for 3.0 is show/hide columns. I’ve been working on my own solution based off #299 @lcb’s solution:

  constructor(props) {
    super(props);
    this.state = { showModal: false, hiddenColumns: {} };
  }

  changeColumn(id) {
    return () => {
      this.setState({ hiddenColumns: Object.assign(this.state.hiddenColumns, { id: !this.state.hiddenColumns.id }) });
    };
  }

however, when using his code only the ID field has its state changed, and the checkbox’s remain stuck in a “checked” state and cannot be toggled. This issue is easily pointed towards Object.assign(this.state.hiddenColumns, { id: !this.state.hiddenColumns.id })

So I cooked up my own solution implementing a nicely styled modal and some code which would probably be considered hacky but it works well! Any optimization tips perhaps? 😃

This table will show/hide any column from popup modal(styles included if needed and lazily added at top), and implements custom CSV export functionality which allows user to select rows to be exported.

// Lazily placed var for holding selectedRows TODO: perhaps make a prop?
var rowsSelected = []

// Function to track which rows are selected and to be exported to csv
function onRowSelect(row, isSelected, e) {
  let rowStr = '';
  for(const prop in row) {
    rowStr += prop + ': "' + row[prop] + "'";
  }
  rowsSelected.push(row);
  console.log(rowsSelected);
}

//CSS Styles for modal:
const modalStyle = {
  position: 'fixed',
  zIndex: 1040,
  top: 0, bottom: 0, left: 0, right: 0
};

const backdropStyle = {
  ...modalStyle,
  zIndex: 'auto',
  backgroundColor: '#000',
  opacity: 0.5
};

const dialogStyle = function() {
  // we use some psuedo random coords so nested modals
  // don't sit right on top of each other.
  let top = 50
  let left = 50

  return {
    position: 'absolute',
    width: 400,
    top: top + '%', left: left + '%',
    transform: `translate(-${top}%, -${left}%)`,
    border: '1px solid #e5e5e5',
    backgroundColor: 'white',
    boxShadow: '0 5px 15px rgba(0,0,0,.5)',
    padding: 20
  };
};

class CyhyTable extends React.Component {
  // Initialize table props/state
  constructor(props) {
    super(props);
    this.state = { showModal: false, hiddenColumns: {} };

  }
  // Hacky solution for dynamic column values
  changeColumn(column) {
    return () => {
      
      var o = {}
      
      // If state.hiddenColumns does not have column name, create object and assign in setState
      // Object.defineProperty is needed so I can use the value of 'column' input parameter
      // Otherwise, simply using 'this.state.hiddenColumn.column' would only add 'column' 
      if(!this.state.hiddenColumns.hasOwnProperty(column)) {
        Object.defineProperty(o, column, {
          value: true,
          enumerable: true  // Object created must be enumerable to be used later in Object.assign()
        })
        console.log("new: ", o)
        this.setState({ hiddenColumns: Object.assign(this.state.hiddenColumns, o) });
      } else {  // If state.hiddenColumns does contain column name object, reassign to o with null val and call setState
        this.setState({ hiddenColumns: Object.assign(!this.state.hiddenColumns, o) });
        console.log("Hopefully false/null!: ", o)
      }
      console.log("state:", this.state.hiddenColumns)
    };
  }

  // Close Modal
  closeColumnDialog = (onClick) => {
    this.setState({ showModal: false });
  }

  // Open Modal
  openColumnDialog = (onClick) => {
    this.setState({ showModal: true });
  }

  // Create custom CSV button HTML/Styling 
  // for integration into custom toolbar
  createCustomExportCSVButton = (onClick) => {
    return (
      <ExportCSVButton 
        className="action button-gray smaller right"
        btnText="Export CSV"
      />
    );
  }

  // What to export
  onExportToCSV(row) {
    return rowsSelected;
  }  

  render() {
    const selectRowProp = {
      mode: 'checkbox',
      onSelect: onRowSelect
    };

    const options = {
      clearSearch: false,
      searchPanel: (props) => (<CyhyTableSearch { ...props }/>),
      onExportToCSV: this.onExportToCSV,
      exportCSVBtn: this.createCustomExportCSVButton,
      toolBar: this.createCustomToolBar,   
    };

    return (
      <div>
        <div className='modal-example'>
          <Button onClick={::this.openColumnDialog}>Visible Columns</Button>
          <Modal 
            show={this.state.showModal} 
            onHide={::this.closeColumnDialog}
            style={modalStyle}
            backdropStyle={backdropStyle}          
            >
            <Modal.Header closeButton />
            <Modal.Body>
              <div style={dialogStyle()} >
                <h4 id='modal-label'>Modify Visible</h4>
                <input type="checkbox" onChange={this.changeColumn('id')} checked={!this.state.hiddenColumns.id} /> ID <br />
                <input type="checkbox" onChange={this.changeColumn('severity')} checked={!this.state.hiddenColumns.severity} /> Severity <br />
                <input type="checkbox" onChange={this.changeColumn('ip')} checked={!this.state.hiddenColumns.ip} /> IP <br />
                <input type="checkbox" onChange={this.changeColumn('port')} checked={!this.state.hiddenColumns.port} /> Port <br />
                <input type="checkbox" onChange={this.changeColumn('dns')} checked={!this.state.hiddenColumns.dns} /> DNS <br />
                <input type="checkbox" onChange={this.changeColumn('vuln')} checked={!this.state.hiddenColumns.vuln} /> Vulnerability <br />
              </div>
            </Modal.Body>
          </Modal>
        </div> 

        <BootstrapTable
          data={ cyhyData }
          options={ options }
          selectRow={ selectRowProp }
          exportCSV={ true }
          tableHeaderClass='flakes-table'
          tableBodyClass='flakes-table'
          containerClass='flakes-table'
          tableContainerClass='flakes-table'
          headerContainerClass='flakes-table'
          bodyContainerClass='flakes-table' 
          search >
      
          <TableHeaderColumn isKey={true} dataField='id' hidden={this.state.hiddenColumns.id}>ID</TableHeaderColumn>
          <TableHeaderColumn dataField='severity' hidden={this.state.hiddenColumns.severity}>Severity</TableHeaderColumn>
          <TableHeaderColumn dataField='ip' hidden={this.state.hiddenColumns.ip}>IP</TableHeaderColumn>
          <TableHeaderColumn dataField='port' hidden={this.state.hiddenColumns.port}>Port</TableHeaderColumn>
          <TableHeaderColumn dataField='dns' hidden={this.state.hiddenColumns.dns}>DNS</TableHeaderColumn>
          <TableHeaderColumn dataField='vuln' hidden={this.state.hiddenColumns.vuln}>Vulnerability</TableHeaderColumn>
        </BootstrapTable>

Everything is working great! Still need to now integrate custom column selector into the toolbar and add sorting/pagination but that stuff should go quick now 😃

Thanks Again!

0reactions
vaishuabhicommented, Dec 1, 2017

hi can u help me with the following error…while adding a new row the background in the popup is not getting changed…wt i need to do for this…i cnt find the css lso…

hre is d code…

import React from ‘react’; import { BootstrapTable, TableHeaderColumn, InsertButton, DeleteButton, SizePerPageDropDown } from ‘react-bootstrap-table’; import ‘./react-bootstrap-table.css’; const jobs = []; const jobTypes = [{ value: ‘A’, text: ‘TYPE_A’ }, { value: ‘B’, text: ‘TYPE_B’ }, { value: ‘C’, text: ‘TYPE_C’ }, { value: ‘D’, text: ‘TYPE_D’ }];

function addJobs(quantity) { const startId = jobs.length; //alert(jobs.length); for (let i = 0; i < quantity; i++) { //alert(jobs.length) const id = startId + i; jobs.push({ id: id, name: 'Item name ’ + id, type1: ‘A’, type2: ‘B’, active: i % 2 === 0 ? ‘Y’ : ‘N’, date: ‘200’ + i + ‘-12-28’ }); } }

addJobs(15);

const cellEditProp = { mode: ‘click’, blurToSave: true }; class ActiveFormatter extends React.Component { render() { return ( ); } }

export default class EditTypeTable extends React.Component {

constructor(props) { super(props); }

formatType(cell) { return TYPE_${cell}; }

jobTypes(row) {

return ['A', 'B'];

}

createCustomInsertButton = (onClick) => {

return (
  <button style={{ color: 'purple' }} onClick={onClick}> <a class="modal hide fade modal2">Add Row</a></button>
);

} createCustomDeleteButton = (onClick) => { return ( <button style={{ color: ‘red’ }} onClick={onClick}>Delete Row</button> ); } createCustomExportCSVButton = (onClick) => { return ( <button style={{ color: ‘blue’ }} onClick={onClick}>Export CSV</button> ); } createCustomClearButton = (onClick) => { return ( <button style={{ color: ‘green’ }} onClick={onClick}>Clear Search</button> ); }

render() { const options = { insertBtn: this.createCustomInsertButton,

  deleteBtn: this.createCustomDeleteButton,
  exportCSVBtn: this.createCustomExportCSVButton,
  clearSearch: true,
  clearSearchBtn: this.createCustomClearButton
 
 // sizePerPageList: [5, 15, 30]
};
const selectRow = {
  mode: 'checkbox',
  bgColor: 'lavender',
  showOnlySelected: true
};
return (
  <div>
  
    <BootstrapTable data={jobs} 
    cellEdit={cellEditProp} 
    options={options} insertRow deleteRow search
     selectRow={selectRow} 
     exportCSV 
     containerStyle={{ background: 'orange' }}
     tableStyle={{ background: '' }}
       >

      <TableHeaderColumn dataField='id' width='150px' isKey={true}>Job ID </TableHeaderColumn>
      <TableHeaderColumn dataField='name' width='150px' filter={{ type: 'TextFilter' }}>Job Name</TableHeaderColumn>
      <TableHeaderColumn dataField='type1' width='150px' dataFormat={this.formatType}
        editable={{ type: 'select', options: { values: jobTypes } }}>Job Type1</TableHeaderColumn>
      <TableHeaderColumn dataField='type2' width='150px' editable={{ type: 'select', options: { values: this.jobTypes } }}>Job Type2</TableHeaderColumn>
      <TableHeaderColumn dataField='active' width='150px' editable={{ type: 'checkbox', options: { values: 'Y:N' } }}>Active</TableHeaderColumn>
      <TableHeaderColumn dataField='date' width='150px' editable={{ type: 'date' }}>Date Time</TableHeaderColumn>
      <TableHeaderColumn dataField='name' width='150px' editable={{ type: 'radio' }} hidden={false}>Hidden col</TableHeaderColumn>

    </BootstrapTable>
  </div>
);

};

}

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why does a custom element collapse? - Stack Overflow
Your SVG element is not being created correctly. It needs to be in the correct SVG namespace. Change it to this: const container...
Read more >
Window.customElements - Web APIs | MDN
The customElements read-only property of the Window interface returns a reference to the CustomElementRegistry object, which can be used to ...
Read more >
RFC: Plan for custom element attributes/properties in React 19 ...
The doc outlines the pros and cons of various approaches React could use to handle attributes and properties on custom elements.
Read more >
Custom Element Best Practices - web.dev
Custom elements let you construct your own HTML tags. This checklist covers best practices to help you build high quality elements.
Read more >
How to add custom google search bar inside your web-page?
Embedding the Search Bar on a Webpage: After getting your code you can simply paste it inside your web page to see the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found