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
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
}
}
}