Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: undefined is not a function (near '...data.store.forEach...') #299

Closed
SamusAranX opened this issue Nov 28, 2021 · 3 comments
Closed
Labels
bug Something isn't working

Comments

@SamusAranX
Copy link

This is the entirety of my autocomplete.js-related code:

var ac;
window.addEventListener("load", function () {
	let config = {
		selector: ".autocomplete",
		data: {
			src: async (query) => {
				try {
					let source = await fetch(SUGGEST_ENDPOINT);
					return await source.json();
				} catch (error) {
					return error;
				}
			},
			keys: ["data"],
			cache: true,
		},
		debounce: 300,
	};
	ac = new autoComplete(config);
}, false);

Typing in the search field causes this error to show up in the console:

[Error] Unhandled Promise Rejection: TypeError: undefined is not a function (near '...data.store.forEach...')
	findMatches (autoComplete.js:302)
	(anonymous function) (autoComplete.js:475)
	promiseReactionJob

What's happening now?

@SamusAranX SamusAranX added the bug Something isn't working label Nov 28, 2021
@folknor
Copy link

folknor commented Nov 28, 2021

I realise you've used the code directly from the documentation, but I've never used await in this way. I don't know what's wrong with your code, but here's how I do it:

src: async (query) => {
	let data
	let url = new URL("foo&q=" + query)
	await fetch(url, ...)
		.then(json => (data = json))
		.catch(error => (data = error))
	if (
		!(data instanceof Object) ||
		... other validation checks
	) {
		return data instanceof Error
			? data
			: new Error(
				"Some kind of error has occurred. Please contact the system administrator."
			)
	}
	return data
}

Make sure that what you return implements forEach. It should be an array of values that has the keys as configured by data.keys.

And then in resultItem.element I check if it's an Error and give the result a different CSS class, and in resultsList.element I check if there's only one matching result and it has the error class I change the look of the dropdown.

There's some example code (for an older version of autoComplete.js) here: #95 (comment) #206 (comment) #207

@folknor
Copy link

folknor commented Nov 28, 2021

Like this

resultItem: {
	selected: "selected",
	element: (element, data) => {
		if (data.value.feil instanceof Error) {
			element.innerHTML = data.value.feil.message
			element.classList.add("feil")
			return
		}
		if (
			data.value.forretningsadresse instanceof Object &&
			typeof data.value.forretningsadresse.poststed === "string"
		) {
			element.innerHTML = `<span>${data.value.navn}</span><span class="text-muted">${data.value.forretningsadresse.poststed}</span>`
		} else if (
			data.value.postadresse instanceof Object &&
			typeof data.value.postadresse.poststed === "string"
		) {
			element.innerHTML = `<span>${data.value.navn}</span><span class="text-muted">${data.value.postadresse.poststed}</span>`
		} else {
			element.innerHTML = `<span>${data.value.navn}</span>`
		}
	}
},
resultsList: {
	tabSelect: true,
	class: "autocomplete",
	element: (element, data) => {
		// query = manipulated query
		// results = rendered results, limited by maxResults etc
		// matches = all matches from the fetched data
		// results + matches = ...{ key: "navn", index: ??, match: "HOGNAMAT AS", value: {brregJson} }
		//const { query, matches, results } = data
		const { query, matches } = data

		if (
			matches.length === 0
		) {
			const result = document.createElement("p")
			let nr = /^\d+$/.test(query)
			if (nr === true) {
				result.classList.add("info")
				result.innerHTML = `<span class="fa fa-question-circle"></span>Helpful message.`
			} else {
				result.innerHTML = `<span class="fa fa-exclamation-triangle"></span>Found no results.`
			}
			element.append(result)
		} else if (
			matches.length === 1 &&
			element.children[0].classList.contains("feil")
		) {
			let feilMelding = element.children[0].innerHTML
			element.innerHTML = ""
			const feil = document.createElement("p")
			feil.classList.add("error", "small")
			feil.innerHTML = `<span class="fa fa-exclamation-triangle"></span>${feilMelding}.`
			element.prepend(feil)
		} else {
			const hjelp = document.createElement("p")
			hjelp.classList.add("info", "small")
			hjelp.innerHTML = `<span class="fa fa-question-circle"></span>Du må velge en bedrift i denne listen. Det er ikke nok å skrive inn navnet eller organisasjonsnummeret.`
			element.prepend(hjelp)
		}
	},
	maxResults: 8,
	noResults: true,
},

helpworks
noresults

@SamusAranX
Copy link
Author

Gotcha, thank you. It's slowly coming together. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants