Coding

Filterable Table

By Paul Mackey on Sun May 15 2022

I recently got tasked with developing a filterable survey table as part of an on going project. The solution would allow users to query a large database of data and be instantly presented with results. I worked alongside a senior Backend Java Developer who designed & developed the BE.

We needed to work closely together to ensure that the BE & FE could 'talk' to each other. We had two weekly stand ups with the clients where we would talk about progress to date & gather feedback / tweaks that were needed.

FE Solution

Screen Shot 2020-08-06 at 20.14.57.png

JS Implementation

export class SurveyTable extends window.HTMLElement {
  connectedCallback () {
    this.el = this
    this.cacheElements()
    this.addEventListeners()
  }

  cacheElements () {
    this.searchResults = this.querySelector('.SurveyTable-ajax')
  }

  addEventListeners () {
    document.body.addEventListener('Dropdown:Updated', el => {
      el.querySelectorAll(':scope ~ .CustomDropdown').forEach(item => {
        item.removeAttribute('selected')
        item.dataset.value = ''
      })
      this.buildQuery()
    })
  }

  buildQuery () {
    var obj = {}
    this.el.querySelectorAll('.CustomDropdown').forEach(filter => {
      let name = filter
        .querySelector('.CustomDropdown-link[selected]')
        .getAttribute('data-name')
      let value = filter
        .querySelector('.CustomDropdown-link[selected]')
        .getAttribute('data-value')
      var pair = { [name]: value }
      obj = { ...obj, ...pair }
    })

    var esc = encodeURIComponent
    let apiUrl =
      window.location.pathname +
      '?' +
      Object.keys(obj)
        .map(k => esc(k) + '=' + esc(obj[k]))
        .join('&')
    this.getNewSearch(apiUrl).then(response => {
      this.renderSearchResults(response)
    })
  }

  getNewSearch (apiUrl) {
    return new Promise((resolve, reject) => {
      window
        .fetch(apiUrl, {
          credentials: 'include'
        })
        .then(response => {
          resolve(response.text())
        })
        .catch(() => {
          reject()
        })
    })
  }

  renderSearchResults (response) {
    let filterDiv = document.createElement('div')
    filterDiv.innerHTML = response
    let searchResultsFromResponse = filterDiv.querySelector('.SurveyTable-ajax')
      .innerHTML

    if (searchResultsFromResponse) {
      this.searchResults.innerHTML = searchResultsFromResponse
    }
  }
}