Bootstrap Typeahead Autocomplete Text Using JavaScript and PHP

Typeahead Autocomplete Text Using JavaScript and PHP is a tutorial that teaches how to create an autocomplete text input for Bootstrap.
Autocomplete Textbox is a very practical feature on web-based applications. If you have hundreds of data and it’s not possible to load everything in a select or dropdown list, then autocomplete is the way to go. When someone types in a textbox, information related to that character will be displayed below, so they can quickly pick which option they are looking for.
In this tutorial we will be using autocomplete.js, a pure JavaScript library that is just like Typeahead and can work with Bootstrap. Bootstrap 5 library is a pretty powerful option and there’s all kinds of tools. Taking vanilla JavaScript to create Typeahead Autocomplete Textboxes for Bootstrap 5 by combining it with PHP and MySQL would be a good place to start, though.
Below, you can find the step by step process of how to implement Typeahead Autocomplete Textbox in your bootstrap 5.
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<?php $connect = new PDO("mysql:host=localhost; dbname=typeahead", "root", ""); $query = "SELECT wc_name FROM world_countries ORDER BY wc_name ASC"; $result = $connect->query($query); $data = array(); foreach($result as $row) { $data[] = array( 'label' => $row['wc_name'], 'value' => $row['wc_name'] ); } ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> <title>Bootstrap Typeahead Autocomplete Text Using JavaScript and PHP</title> </head> <body> <div class="container"> <h1 class="mt-5 mb-4 text-center text-primary">Bootstrap Typeahead Autocomplete Text Using JavaScript and PHP</h1> <div class="row d-flex justify-content-center"> <div class="col-md-4"> <input type="text" name="wc_code" id="wc_code" class="form-control form-control-lg" placeholder="Enter Country" /> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script> <script src="autocomplete.js"></script> <script> var auto_complete = new Autocomplete(document.getElementById('wc_code'), { data:<?php echo json_encode($data); ?>, maximumItems:10, highlightTyped:true, highlightClass : 'fw-bold text-success' }); </script> </body> </html> |
autocomplete.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
const DEFAULTS = { threshold: 2, maximumItems: 5, highlightTyped: true, highlightClass: 'text-success', label: 'label', value: 'value', showValue: false, showValueBeforeLabel: false, }; class Autocomplete { constructor(field, options) { this.field = field; this.options = Object.assign({}, DEFAULTS, options); this.dropdown = null; field.parentNode.classList.add('dropdown'); field.setAttribute('data-bs-toggle', 'dropdown'); field.classList.add('dropdown-toggle'); const dropdown = ce(`<div class="dropdown-menu"></div>`); if (this.options.dropdownClass) dropdown.classList.add(this.options.dropdownClass); insertAfter(dropdown, field); this.dropdown = new bootstrap.Dropdown(field, this.options.dropdownOptions); field.addEventListener('click', (e) => { if (this.createItems() === 0) { e.stopPropagation(); this.dropdown.hide(); } }); field.addEventListener('input', () => { if (this.options.onInput) this.options.onInput(this.field.value); this.renderIfNeeded(); }); field.addEventListener('keydown', (e) => { if (e.keyCode === 27) { this.dropdown.hide(); return; } if (e.keyCode === 40) { this.dropdown._menu.children[0]?.focus(); return; } }); } setData(data) { this.options.data = data; this.renderIfNeeded(); } renderIfNeeded() { if (this.createItems() > 0) this.dropdown.show(); else this.field.click(); } createItem(lookup, item) { let label; if (this.options.highlightTyped) { const idx = removeDiacritics(item.label) .toLowerCase() .indexOf(removeDiacritics(lookup).toLowerCase()); const className = Array.isArray(this.options.highlightClass) ? this.options.highlightClass.join(' ') : (typeof this.options.highlightClass == 'string' ? this.options.highlightClass : ''); label = item.label.substring(0, idx) + `<span class="${className}">${item.label.substring(idx, idx + lookup.length)}</span>` + item.label.substring(idx + lookup.length, item.label.length); } else { label = item.label; } if (this.options.showValue) { if (this.options.showValueBeforeLabel) { label = `${item.value} ${label}`; } else { label += ` ${item.value}`; } } return ce(`<button type="button" class="dropdown-item" data-label="${item.label}" data-value="${item.value}">${label}</button>`); } createItems() { const lookup = this.field.value; if (lookup.length < this.options.threshold) { this.dropdown.hide(); return 0; } const items = this.field.nextSibling; items.innerHTML = ''; const keys = Object.keys(this.options.data); let count = 0; for (let i = 0; i < keys.length; i++) { const key = keys[i]; const entry = this.options.data[key]; const item = { label: this.options.label ? entry[this.options.label] : key, value: this.options.value ? entry[this.options.value] : entry }; if (removeDiacritics(item.label).toLowerCase().indexOf(removeDiacritics(lookup).toLowerCase()) >= 0) { items.appendChild(this.createItem(lookup, item)); if (this.options.maximumItems > 0 && ++count >= this.options.maximumItems) break; } } this.field.nextSibling.querySelectorAll('.dropdown-item').forEach((item) => { item.addEventListener('click', (e) => { let dataLabel = e.target.getAttribute('data-label'); let dataValue = e.target.getAttribute('data-value'); this.field.value = dataLabel; if (this.options.onSelectItem) { this.options.onSelectItem({ value: dataValue, label: dataLabel }); } this.dropdown.hide(); }) }); return items.childNodes.length; } } /** * @param html * @returns {Node} */ function ce(html) { let div = document.createElement('div'); div.innerHTML = html; return div.firstChild; } /** * @param elem * @param refElem * @returns {*} */ function insertAfter(elem, refElem) { return refElem.parentNode.insertBefore(elem, refElem.nextSibling); } /** * @param {String} str * @returns {String} */ function removeDiacritics(str) { return str .normalize('NFD') .replace(/[\u0300-\u036f]/g, ''); } |
Database
Create “typeahead” table and use below database structure.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
-- -- Database: `typeahead` -- -- -------------------------------------------------------- -- -- Table structure for table `world_countries` -- CREATE TABLE `world_countries` ( `id` int(11) NOT NULL, `wc_code` varchar(2) NOT NULL DEFAULT '', `wc_name` varchar(100) NOT NULL DEFAULT '' ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- -- Dumping data for table `world_countries` -- INSERT INTO `world_countries` (`id`, `wc_code`, `wc_name`) VALUES (1, 'AF', 'Afghanistan'), (2, 'AL', 'Albania'), (3, 'DZ', 'Algeria'), (4, 'DS', 'American Samoa'), (5, 'AD', 'Andorra'), (6, 'AO', 'Angola'), (7, 'AI', 'Anguilla'), (8, 'AQ', 'Antarctica'), (9, 'AG', 'Antigua and Barbuda'), (10, 'AR', 'Argentina'), (11, 'AM', 'Armenia'), (12, 'AW', 'Aruba'), (13, 'AU', 'Australia'), (14, 'AT', 'Austria'), (15, 'AZ', 'Azerbaijan'), (16, 'BS', 'Bahamas'), (17, 'BH', 'Bahrain'), (18, 'BD', 'Bangladesh'), (19, 'BB', 'Barbados'), (20, 'BY', 'Belarus'), (21, 'BE', 'Belgium'), (22, 'BZ', 'Belize'), (23, 'BJ', 'Benin'), (24, 'BM', 'Bermuda'), (25, 'BT', 'Bhutan'), (26, 'BO', 'Bolivia'), (27, 'BA', 'Bosnia and Herzegovina'), (28, 'BW', 'Botswana'), (29, 'BV', 'Bouvet Island'), (30, 'BR', 'Brazil'), (31, 'IO', 'British Indian Ocean Territory'), (32, 'BN', 'Brunei Darussalam'), (33, 'BG', 'Bulgaria'), (34, 'BF', 'Burkina Faso'), (35, 'BI', 'Burundi'), (36, 'KH', 'Cambodia'), (37, 'CM', 'Cameroon'), (38, 'CA', 'Canada'), (39, 'CV', 'Cape Verde'), (40, 'KY', 'Cayman Islands'), (41, 'CF', 'Central African Republic'), (42, 'TD', 'Chad'), (43, 'CL', 'Chile'), (44, 'CN', 'China'), (45, 'CX', 'Christmas Island'), (46, 'CC', 'Cocos (Keeling) Islands'), (47, 'CO', 'Colombia'), (48, 'KM', 'Comoros'), (49, 'CG', 'Congo'), (50, 'CK', 'Cook Islands'), (51, 'CR', 'Costa Rica'), (52, 'HR', 'Croatia (Hrvatska)'), (53, 'CU', 'Cuba'), (54, 'CY', 'Cyprus'), (55, 'CZ', 'Czech Republic'), (56, 'DK', 'Denmark'), (57, 'DJ', 'Djibouti'), (58, 'DM', 'Dominica'), (59, 'DO', 'Dominican Republic'), (60, 'TP', 'East Timor'), (61, 'EC', 'Ecuador'), (62, 'EG', 'Egypt'), (63, 'SV', 'El Salvador'), (64, 'GQ', 'Equatorial Guinea'), (65, 'ER', 'Eritrea'), (66, 'EE', 'Estonia'), (67, 'ET', 'Ethiopia'), (68, 'FK', 'Falkland Islands (Malvinas)'), (69, 'FO', 'Faroe Islands'), (70, 'FJ', 'Fiji'), (71, 'FI', 'Finland'), (72, 'FR', 'France'), (73, 'FX', 'France, Metropolitan'), (74, 'GF', 'French Guiana'), (75, 'PF', 'French Polynesia'), (76, 'TF', 'French Southern Territories'), (77, 'GA', 'Gabon'), (78, 'GM', 'Gambia'), (79, 'GE', 'Georgia'), (80, 'DE', 'Germany'), (81, 'GH', 'Ghana'), (82, 'GI', 'Gibraltar'), (83, 'GK', 'Guernsey'), (84, 'GR', 'Greece'), (85, 'GL', 'Greenland'), (86, 'GD', 'Grenada'), (87, 'GP', 'Guadeloupe'), (88, 'GU', 'Guam'), (89, 'GT', 'Guatemala'), (90, 'GN', 'Guinea'), (91, 'GW', 'Guinea-Bissau'), (92, 'GY', 'Guyana'), (93, 'HT', 'Haiti'), (94, 'HM', 'Heard and Mc Donald Islands'), (95, 'HN', 'Honduras'), (96, 'HK', 'Hong Kong'), (97, 'HU', 'Hungary'), (98, 'IS', 'Iceland'), (99, 'IN', 'India'), (100, 'IM', 'Isle of Man'), (101, 'ID', 'Indonesia'), (102, 'IR', 'Iran (Islamic Republic of)'), (103, 'IQ', 'Iraq'), (104, 'IE', 'Ireland'), (105, 'IL', 'Israel'), (106, 'IT', 'Italy'), (107, 'CI', 'Ivory Coast'), (108, 'JE', 'Jersey'), (109, 'JM', 'Jamaica'), (110, 'JP', 'Japan'), (111, 'JO', 'Jordan'), (112, 'KZ', 'Kazakhstan'), (113, 'KE', 'Kenya'), (114, 'KI', 'Kiribati'), (115, 'KP', 'Korea, Democratic People\'s Republic of'), (116, 'KR', 'Korea, Republic of'), (117, 'XK', 'Kosovo'), (118, 'KW', 'Kuwait'), (119, 'KG', 'Kyrgyzstan'), (120, 'LA', 'Lao People\'s Democratic Republic'), (121, 'LV', 'Latvia'), (122, 'LB', 'Lebanon'), (123, 'LS', 'Lesotho'), (124, 'LR', 'Liberia'), (125, 'LY', 'Libyan Arab Jamahiriya'), (126, 'LI', 'Liechtenstein'), (127, 'LT', 'Lithuania'), (128, 'LU', 'Luxembourg'), (129, 'MO', 'Macau'), (130, 'MK', 'Macedonia'), (131, 'MG', 'Madagascar'), (132, 'MW', 'Malawi'), (133, 'MY', 'Malaysia'), (134, 'MV', 'Maldives'), (135, 'ML', 'Mali'), (136, 'MT', 'Malta'), (137, 'MH', 'Marshall Islands'), (138, 'MQ', 'Martinique'), (139, 'MR', 'Mauritania'), (140, 'MU', 'Mauritius'), (141, 'TY', 'Mayotte'), (142, 'MX', 'Mexico'), (143, 'FM', 'Micronesia, Federated States of'), (144, 'MD', 'Moldova, Republic of'), (145, 'MC', 'Monaco'), (146, 'MN', 'Mongolia'), (147, 'ME', 'Montenegro'), (148, 'MS', 'Montserrat'), (149, 'MA', 'Morocco'), (150, 'MZ', 'Mozambique'), (151, 'MM', 'Myanmar'), (152, 'NA', 'Namibia'), (153, 'NR', 'Nauru'), (154, 'NP', 'Nepal'), (155, 'NL', 'Netherlands'), (156, 'AN', 'Netherlands Antilles'), (157, 'NC', 'New Caledonia'), (158, 'NZ', 'New Zealand'), (159, 'NI', 'Nicaragua'), (160, 'NE', 'Niger'), (161, 'NG', 'Nigeria'), (162, 'NU', 'Niue'), (163, 'NF', 'Norfolk Island'), (164, 'MP', 'Northern Mariana Islands'), (165, 'NO', 'Norway'), (166, 'OM', 'Oman'), (167, 'PK', 'Pakistan'), (168, 'PW', 'Palau'), (169, 'PS', 'Palestine'), (170, 'PA', 'Panama'), (171, 'PG', 'Papua New Guinea'), (172, 'PY', 'Paraguay'), (173, 'PE', 'Peru'), (174, 'PH', 'Philippines'), (175, 'PN', 'Pitcairn'), (176, 'PL', 'Poland'), (177, 'PT', 'Portugal'), (178, 'PR', 'Puerto Rico'), (179, 'QA', 'Qatar'), (180, 'RE', 'Reunion'), (181, 'RO', 'Romania'), (182, 'RU', 'Russian Federation'), (183, 'RW', 'Rwanda'), (184, 'KN', 'Saint Kitts and Nevis'), (185, 'LC', 'Saint Lucia'), (186, 'VC', 'Saint Vincent and the Grenadines'), (187, 'WS', 'Samoa'), (188, 'SM', 'San Marino'), (189, 'ST', 'Sao Tome and Principe'), (190, 'SA', 'Saudi Arabia'), (191, 'SN', 'Senegal'), (192, 'RS', 'Serbia'), (193, 'SC', 'Seychelles'), (194, 'SL', 'Sierra Leone'), (195, 'SG', 'Singapore'), (196, 'SK', 'Slovakia'), (197, 'SI', 'Slovenia'), (198, 'SB', 'Solomon Islands'), (199, 'SO', 'Somalia'), (200, 'ZA', 'South Africa'), (201, 'GS', 'South Georgia South Sandwich Islands'), (202, 'ES', 'Spain'), (203, 'LK', 'Sri Lanka'), (204, 'SH', 'St. Helena'), (205, 'PM', 'St. Pierre and Miquelon'), (206, 'SD', 'Sudan'), (207, 'SR', 'Suriname'), (208, 'SJ', 'Svalbard and Jan Mayen Islands'), (209, 'SZ', 'Swaziland'), (210, 'SE', 'Sweden'), (211, 'CH', 'Switzerland'), (212, 'SY', 'Syrian Arab Republic'), (213, 'TW', 'Taiwan'), (214, 'TJ', 'Tajikistan'), (215, 'TZ', 'Tanzania, United Republic of'), (216, 'TH', 'Thailand'), (217, 'TG', 'Togo'), (218, 'TK', 'Tokelau'), (219, 'TO', 'Tonga'), (220, 'TT', 'Trinidad and Tobago'), (221, 'TN', 'Tunisia'), (222, 'TR', 'Turkey'), (223, 'TM', 'Turkmenistan'), (224, 'TC', 'Turks and Caicos Islands'), (225, 'TV', 'Tuvalu'), (226, 'UG', 'Uganda'), (227, 'UA', 'Ukraine'), (228, 'AE', 'United Arab Emirates'), (229, 'GB', 'United Kingdom'), (230, 'US', 'United States'), (231, 'UM', 'United States minor outlying islands'), (232, 'UY', 'Uruguay'), (233, 'UZ', 'Uzbekistan'), (234, 'VU', 'Vanuatu'), (235, 'VA', 'Vatican City State'), (236, 'VE', 'Venezuela'), (237, 'VN', 'Vietnam'), (238, 'VG', 'Virgin Islands (British)'), (239, 'VI', 'Virgin Islands (U.S.)'), (240, 'WF', 'Wallis and Futuna Islands'), (241, 'EH', 'Western Sahara'), (242, 'YE', 'Yemen'), (243, 'ZR', 'Zaire'), (244, 'ZM', 'Zambia'), (245, 'ZW', 'Zimbabwe'); -- -- Indexes for dumped tables -- -- -- Indexes for table `world_countries` -- ALTER TABLE `world_countries` ADD PRIMARY KEY (`id`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `world_countries` -- ALTER TABLE `world_countries` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=246; COMMIT; |
If you follow the steps outlined in this post then you can add a Typeahead autcomplete textfield in your Bootstrap website. This is done using JavaScript and PHP / MySQL database.
AutocompleteBootstrapJavaScriptTypeahead
Mraj
Creative Designer & Developer specialist by the spirit and a loving blogger by thoughts. If you have any questions let me drop an email with the article name to the following email id: [email protected]