AllenFang / react-bootstrap-table

A Bootstrap table built with React.js
https://allenfang.github.io/react-bootstrap-table/
MIT License
2.23k stars 782 forks source link

Search with filterValue on array of objects(complex data) #1833

Open ghost opened 6 years ago

ghost commented 6 years ago

I've read a lot of closed issues in similar search and filtering data, but can't make mine to work. Sorry for long post, but I want to make this as clear as possible.

ISSUE: When searching(main search on top), I'd like filterValue to be used on some columns. It does not work(at least in my case).

What's complex on my end is that I have this type of data:

{
    "id" : "B001D8HP60",
    "note" : "This is a note #1",
    "links" : [ 
        {
            "url" : "https://google.com/v",
            "urlNote" : "Url note",
            "businessId" : "7563iTq9qhBtumv8q"
        }, 
        {
            "url" : "https://google.com/v1",
            "urlNote" : "Url note1",
            "businessId" : "u5hxZ562NHnZj849k"
        }, 
        {
            "url" : "https://google.com/v3",
            "businessId" : "pgCdDSXCcLYWxkmrw"
        }
    ]
}

Here's how I display it(love this project, btw): image

Searching works perfectly on simple data such as PID column.(shown on screenshot).

However, it does NOT work on URLs and Business columns.

Here are some of the snippets of my code: HTML:

<BootstrapTable data={documents} ref="documentsTable" striped hover pagination deleteRow insertRow search multiColumnSearch multiColumnSort searchPlaceholder="Search All Data" selectRow={selectRow} options={options}>
            <TableHeaderColumn dataField='_id' isKey hidden>ID</TableHeaderColumn>
            <TableHeaderColumn dataField='id' dataSort dataFormat={ this.formatID.bind(this) } filter={{type: 'TextFilter'}} >PID</TableHeaderColumn>
            <TableHeaderColumn dataField='links.url' searchable dataFormat={ this.formatURLs.bind(this) }
                               filter={ { type: 'TextFilter' } } filterValue={ this.filterUrlValue.bind(this) }>
              URLs</TableHeaderColumn>
            <TableHeaderColumn dataField='links.bId' searchable dataFormat={ this.formatBusiness.bind(this) }
                               filter={ { type: 'TextFilter' } } filterValue={ this.filterBusinessValue.bind(this) }>
              Business</TableHeaderColumn>
            <TableHeaderColumn dataField='action' dataFormat={this.actions.bind(this)} width='120px' dataAlign='right'>
              Actions</TableHeaderColumn>
          </BootstrapTable>

NOTICE, on 3rd and 4th TableHeaderColumn I had to make custom dataField. Initially I had the both equal to links, but my filtering did NOT work properly for both columns(only last filterValue would be used). So I used custom names.

JS:

filterUrlValue(cell, row) {
    const links = row && row.links;
    // option 1: returning the array value (commented out)
    // return links && links.map(link => link.url);

    // option 2: returning the single string to be searched on(array is separated by random chars: `:::`)
    const urls = links && links.map(link => link.url);
    return urls && urls.join(":::");
  }

  filterBusinessValue(cell, row) {
    const links = row && row.links;
    return links && links.map(link => {
      const business = this.getBusiness(link.businessId);
      return business && business.name;
    });
  }

.

So, when I use filters on URLs or Business, it works AWESOME. But when I try to search for the same values in main search these do not work. Any help?

My guess is that it's related to custom dataField names that I use.

ghost commented 6 years ago

P.S. I've found that there is a way to do remote table where I would have to provide all the functions for sorting and filtering, but I'd want to try to avoid that.

ghost commented 6 years ago

Any help?

AllenFang commented 6 years ago

@max-litv it's sorry for lately reply,

For your question, the problems like you said, because the dataField. Currently, there's still a solution is remote, remote allow you to configure search only for remote handling, check this example, configure remoteObj.search as true will only enable search as remote mode.

BTW, you give a good point that many people will have different column which is not corresponding to specified field, like your case.

I'll handle this issue in react-bootstrap-table2

TonyTheHorse commented 6 years ago

Hi Allen

Is there any update of this issue in react-bootstrap-table2 ?

kdolan commented 2 years ago

I was able to solve using a Custom Search Component documented here https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/basic-search.html#customize-search-component

Example

       const CustomSearchComponent = (props) => {
            let input;
            const handleChange = (e) => {
                return customAsyncSerachOnServer(input.value)
                    .then(result=> {
                        if(result!== null) //If a result was found change the search value to the id of the result to get single match
                            props.onSearch(result.id);
                        else //Use the default built in search logic and pass the value through
                            props.onSearch(input.value);
                    })
            };
            return (
                <div>
                    <input
                        className="form-control"
                        ref={ n => input = n }
                        type="text"
                        style={{width: "15%"}}
                        placeholder="Search"
                        onChange={ handleChange }
                    />
                </div>
            );
        };`