bootstrap-select icon indicating copy to clipboard operation
bootstrap-select copied to clipboard

Dynamically adding new items to select when live searching - offer GUI option

Open hrvoj3e opened this issue 4 years ago • 2 comments

I know it seems strange because select should offer a controlled list but I found one use case.

My use case:

  • replace multiple input fields with dropdown
  • use checked mark to show selected items
    • user can toggle items and reconsider
    • user can add new items

I think it would be useful to have a feature alongside live search where one could add new items to dropdown list when search does not find requested term. Steps:

  • search something
    • zero results - did not find anything
  • offer plus/add button in GUI to add new item to select
  • refresh select

hrvoj3e avatar Jan 12 '21 10:01 hrvoj3e

Slim Select can do this with it's addable option: https://slimselectjs.com/options

Would be great to see it come to bootstrap-select too.

cocowalla avatar Jun 14 '22 11:06 cocowalla

I have used this workaround to get "add new" functionality inside the dropdown: Feel free to get inspired :)

HTML

<select name="location" id="location" class="form-control selectpicker" data-live-search="true" data-live-search-normalize="true" data-sanitize="false" data-live-search-placeholder="Search locations..." data-size="15" title="Choose location..." required>
	<option class="add-item" data-content="<input type='text' class='new-loc-input my-1' onKeyDown='event.stopPropagation();' onKeyPress='addSelectInpKeyPress(this,event)' onClick='event.stopPropagation()' placeholder='Create new location'> <i class='fa fa-plus add-new-icon px-1' aria-hidden='true' onClick='addSelectItem(this,event,1);'></i>"></option>
	<option data-divider="true"></option>
</select>

CSS:


a.add-item {
	cursor: default !important;
	pointer-events: none;
}
a.add-item .text {
	display: block !important;
}
a.add-item.active, a.add-item:active {
	background-color: transparent;
}
.new-loc-input {
	border:0;
	outline: none;
	width: 40%;
	pointer-events: auto;
}
.new-loc-input:hover {
	background-color: #f5f5f5;
}
.add-new-icon {
	color: #aaa;
	cursor: pointer;
	pointer-events: auto;
}
.add-new-icon:hover {
	color: #222;
}

javascript (jqeury)

$(function() {
	// data-sanitize="false" on the select element doesn't seem to work so we go for js initialization os selectpicker
	$('.selectpicker').selectpicker({
		sanitize: false,
	});
});

function addSelectItem(option, event) {
	event.stopPropagation();
	let $bootstrap_select = $(option).closest('.bootstrap-select');
	let $select = $bootstrap_select.find('select');
	let $input = $bootstrap_select.find('.new-loc-input');
	let new_location_name = $input.val();
	if ($.trim(new_location_name) === '') {
		return;
	}
	$input.prop('disabled', true);
	let $icon = $bootstrap_select.find('.add-new-icon').removeClass('fa-plus').addClass('fa-spin fa-spinner');
	SOME_AJAX_CALL({
		name: new_location_name,
	}, function(data) {
		$icon.removeClass('fa-spin fa-spinner').addClass('fa-plus');
		if (data.success) {
			let $new_option = $("<option>", {
				selected: true,
				text: new_location_name,
				value: data.group_id,
			});
			$new_option.insertAfter($select.find('option:nth-child(3)'));
			$select.selectpicker('refresh');
		} else {
			let $error_message = $('.error-message').hide().removeClass('d-none');
			$error_message.find('span').text(data.error_message);
			$error_message.slideDown();
		}
	});
}

function addSelectInpKeyPress(option, event) {
	event.stopPropagation();
	// enter character submits the new option
	if (event.which == 13) {
		event.preventDefault();
		addSelectItem($(option).next(),event);
	}
}

scr4bble avatar Nov 23 '23 19:11 scr4bble