0

I want to use a v-text-field to allow the user to filter the results as they are typing them in for the various rows of the v-data-table. The <td>'s of the v-data-table are Arrays also though, which makes the built-in search functionality of v-data-table not work. I'm trying to create either a customer filter or some sort of item-key that will help the normal search filter work properly for the nested data within the <td>. Using "vuetify": "^1.5.16", and "vue": "^2.6.10"

Codepen Link Here - Vuetify v-data-table help

<div id="app">
  <v-app>
    <v-layout>
        <v-flex xs8 offset-xs2>
          <v-text-field
            v-model="search"
            append-icon="search"
            label="Filter Results"
            single-line
            hide-details
          ></v-text-field>
        </v-flex>
      </v-layout>
      <v-card>
        <v-data-table :items="newCustomerArray"
        :headers="headers"
        :search="search"
        >
          <template v-slot:items="props">
            <tr :style="{'backgroundColor': props.index % 2 ? 'rgba(31,150,186, 0.2)' : '#fff'}">
              <td>
                <v-layout column>
                  <v-flex v-for="(pos, i) in props.item" :key="i" pa-2>
                    {{ pos.systemCode.code | nullCheck }}
                  </v-flex>
                </v-layout>
              </td>
              <td>
                <v-layout column>
                  <v-flex v-for="(numberOfPlace, i) in props.item" :key="i" pa-2>
                    {{ numberOfPlace.numberOfPlace | nullCheck }}
                  </v-flex>
                </v-layout>
              </td>
              <td>
                <v-layout column>
                  <v-flex v-for="(firstName, i) in props.item" :key="i" pa-2>
                    {{ firstName.customerName.firstName | nullCheck }}
                  </v-flex>
                </v-layout>
              </td>
              <td>
                <v-layout column>
                  <v-flex v-for="(lastName, i) in props.item" :key="i" pa-2>
                    {{ lastName.customerName.lastName | nullCheck }}
                  </v-flex>
                </v-layout>
              </td>
              <td>
                <v-layout column>
                  <v-flex v-for="(dob, i) in props.item" :key="i" pa-2>
                    {{ dob.dob | nullCheck }}
                  </v-flex>
                </v-layout>
              </td>
              <td>
                <v-layout column>
                  <v-flex v-for="(customerContactsPhone, i) in props.item" :key="i" pa-2>
                    {{ getCustContacts(customerContactsPhone.customerContactsPhone, 'phone') | nullCheck }}
                  </v-flex>
                </v-layout>
              </td>
              <td>
                <v-layout column>
                  <v-flex v-for="(customerContactsEmail, i) in props.item" :key="i" pa-2>
                    {{ getCustContacts(customerContactsEmail.customerContactsEmail, 'email') | nullCheck }}
                  </v-flex>
                </v-layout>
              </td>
            </tr>
          </template>
        </v-data-table>
  </v-app>
</div>
  • So you're just trying to find table-rows (``) based on when any `` within a row matches your filter query? – Andrew Nov 13 '19 at 19:17
  • yeah, essentially, but I need to be able to search the multiple data points within a `` since there can be multiple customers under the same id, but with differing other information, I need to be able to check each of the customers within the group within the `` – ClemsonTigerJB3 Nov 13 '19 at 19:38
  • It looks like you're going to need to write a more complex filtering function for this, using JS's Array.prototype.filter function. Is that specifically what you need help with? – Andrew Nov 13 '19 at 19:47
  • Secondly: You *can* write this as a computed function so that your list will update immediately on each keypress (and then your v-for would loop over the computed version instead of the raw data), but with such a complexity and length as you have in this example I don't know if that'd be very performant. (I'd personally just add a button or just put a cap on the maximum update interval, or something) – Andrew Nov 13 '19 at 19:49
  • Also, this data sort of looks like it's coming from an API response? If that's accurate you could consider dodging the complexity here altogether if the API offers filtering functionality built-in (at the time of request). It wouldn't be real-time but it'd work. – Andrew Nov 13 '19 at 19:50
  • Yeah, I have tried to customer filter, but the functions I made were not successful. Any thoughts on what might work given the shape of the data. The API is unfortunately not a great one. – ClemsonTigerJB3 Nov 13 '19 at 20:13
  • [This tutorial](https://www.positronx.io/javascript-filter-array-method/) looks promising. Your filter function will need to check each relevant attribute of each object within the `customerSearchArray`. If the value of any of these attributes contains the search text as a substring, your filter function will return true. If none of them match the search text, your filter function should return false. Does that help? – Andrew Nov 13 '19 at 20:17
  • Yes, it does. Thank you. I just need to filter and return { obj.key === searchVal || obj.key2 === searchVal .. and so on } I think. – ClemsonTigerJB3 Nov 13 '19 at 20:22
  • Sounds about right! Better yet, you can [check for substrings](https://stackoverflow.com/questions/1789945/how-to-check-whether-a-string-contains-a-substring-in-javascript#1789952) instead of exact matches. Happy to help. – Andrew Nov 13 '19 at 20:26

1 Answers1

0
 handleFilterCustomerTable(searchInput) {
    this.filteredCustomerTable = this.originalCustomerTable.filter(cust => {
        let rowText = '';
        cust.forEach(c => {
            rowText += this.createSearchText(
              c.pos,
              c.centerNumber,
              this.formatSSN(c.ssn),
              c.firstName,
              c.lastName,
              c.dob,
              c.phone,
              c.email,
              c.custId
            );
          });
          return rowText.toLocaleLowerCase().indexOf(searchInput.toLocaleLowerCase()) >= 0;
        });
     },
      createSearchText(...inputs) {
         return inputs.join('\0'); // '\0' is the literal null character
     },
  • Can you explain why this is the answer to your question? While posting code that solves the issue is nice, having an explanation for future users is helpful. – ninja coder Oct 31 '20 at 02:00