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

Dynamically add results without reinitiating the typeahead #206

Open
simplenotezy opened this issue Jan 6, 2020 · 5 comments
Open

Dynamically add results without reinitiating the typeahead #206

simplenotezy opened this issue Jan 6, 2020 · 5 comments

Comments

@simplenotezy
Copy link

Is there a way to dynamically add new content without reinitiating the typeahead?

For instance, a specific usecase, I need to show a result that is dependent on the user input. For instance, if the typeahead value is "something", I need to display a result, where the datum.value is "bla bla something"

Seems mentioned here as well: #161

@simplenotezy
Copy link
Author

This is a workaround that seems to do the trick:

			typeaheadInput.on('keydown keyup', function() {
				var value = typeaheadInput.val();

				bloodHound.add([{ value: butler.value(), name: 'Search for: ' + typeaheadInput.val() }]);
				typeaheadInput.typeahead('val', '').typeahead('val', value);
			});

Obviously I also need to figure out a way to delete the old appended value.

@simplenotezy
Copy link
Author

Although my hacky workaround is on the way, there are many obstacles. Ideally, a function to "re-render" suggestions is needed. Listening on keyup/keydown is too agreesive, and wont work with "CTRL+A" for instance.

Using keyup works a long way, but after the suggestion has been added, you need to add a space or delete and reenter the latest typed letter, before the suggestion appears, because suggestions have already been rendered. It would be very nice if you could trigger the event to "rerender" suggestions.

@simplenotezy
Copy link
Author

simplenotezy commented Jan 6, 2020

This is my hacky workaround. It does the job, but would be sweet with some more direct APIs.

The solution is to create a new dataset, just for the dynamic keywords, as there is no way to remove a specific suggestion from an existing bloodhound engine.

var dynamicResults = new Bloodhound({
	datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
	queryTokenizer: Bloodhound.tokenizers.whitespace
});

typeaheadInput.on('keydown', function(event) {
	var reservedKeys = [9,13,16,17,18,19,20,32,35,36,37,38,39,40,91,93,224]; // reserved keys (ctrl, space, shift, etc)

	if(!event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey && $.inArray(event.keyCode,reservedKeys) === -1) {
		typeaheadInput.trigger('change');
	}
});

typeaheadInput.on('change', function(event) {
	setTimeout(function() {
		var value = butler.typeaheadInput.val();
		
		dynamicResults.clear();

		dynamicResults.add([
			{
				value: 'Search for ' + value,
				name: 'Search for ' + value
			}
		]);

		typeaheadInput.typeahead('val', '').typeahead('val', '-').typeahead('val', value);
	}, 10);
});

@simplenotezy
Copy link
Author

After seeing the documentation and that you can show suggestions if no query has been made, I tweaked this code, and figured out an even better solution. More clean, and doesn't depend on events workaround.

var dynamicResults = new Bloodhound({
	datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
	queryTokenizer: Bloodhound.tokenizers.whitespace,
	identify: function(obj) { return obj.value; },
});

function dynamicResultsFetch(q, sync) {
	var value = q;
	var suggestionValues = [];

	dynamicResults.clear(); // clear previous suggestions for custom events

	/**
	 * The suggestion object
	 */
	
		var suggestion = {
			value: 'Search for ' + value,
			name: 'Search for ' + value
		};

	/**
	 * Append the suggestion 
	 */

		dynamicResults.add(suggestion);
		suggestionValues.push(suggestion.value);

	/**
	 * Select the ones that matches
	 */

		sync(dynamicResults.get(customEventValues));
}

/**
 * initiate the typeahead
 * @type {Boolean}
 */

	$('input').typeahead(
		{
			hint: true,
			autoselect: true,
			highlight: false
		},
		{
			name: 'dynamicResults',
			source: dynamicResultsFetch,
			display: 'name',
			limit: 5,
		},
		{
			name: 'results',
			source: otherEngine,
			display: 'name',
			limit: 20,
			templates: {
				// empty: [
				// 	'<div class="empty-message">',
				// 		'unable to find any Best Picture winners that match the current query',
				// 	'</div>'
				// ].join('\n'),
				suggestion: Handlebars.compile(template)
			}
		}
	);

@Chealer
Copy link

Chealer commented Jul 30, 2021

I unfortunately do not understand your question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants