Reputation: 319
I have created an autocomplete input, it works well but i want to expand it and make it better. But this is a struggle with my limited jquery ui knowledge and despite some trial and error i cannot seem to work out two problems.
The first problem i would like to address is making the noresult label not selectable meaning that it can't be added to the input on focus or on select or at all.
I want to make it so that if what the user has entered into the input box matched the label value but they did not select it for some reason then when they press the submit button on my form the label that is a match is selected and therefore inputted.
Here is what i have so far:
html:
<div class="search-homepage-input">
{!! Form::open(['route' => 'search.index', 'method' => 'GET']) !!}
<div class="col-md-9 col-l">
{!! Form::text('sl', null, array('class' => 'form-control shop-input', 'maxlength' =>'50', 'placeholder' => 'Search by city. Eg. London, New York, Paris...', 'id' => 'sl')) !!}
</div>
{!! Form::hidden('country', null, array('id' => 'country')) !!}
{!! Form::hidden('city', null, array('id' => 'city')) !!}
<div class="col-md-3 col-r">
{!! Form::submit('Find Shops', array('class' => 'btn btn-homepage-search')) !!}
</div>
{!! Form::close() !!}
</div>
PHP laravel:
public function autoComplete(Request $request){
$query = $request->term;
$res = City::where('name', 'LIKE', "%$query%")->orderBy('name')->paginate(5);
foreach($res as $cities ){
$usersArray[] = array(
"label" => $cities->name,
"value" => $cities->id,
"country" => $cities->countries->id,
"countryname" => $cities->countries->country
);
}
return response()->json($usersArray);
}
JS:
$('#sl').autocomplete({
source: '/autocomplete',
select: function(event, ui) {
event.preventDefault();
$("#country").val(ui.item.country); // save selected id to hidden input
$("#city").val(ui.item.value); // save selected id to hidden input
$('#sl').val(ui.item.label +', '+ ui.item.countryname)
},
focus: function(event, ui){
event.preventDefault();
$('#sl').val(ui.item.label+', '+ui.item.countryname);
},
response: function(event, ui) {
if (!ui.content.length) {
var noResult = { value:"",label:'No results found', countryname:"" };
ui.content.push(noResult);
}
}
}).autocomplete( "instance" )._renderItem = function( ul, item ) {
var li = $("<li>");
if (item.country == undefined) {
li.append("<div>" + item.label +"</div>");
} else {
li.append("<div><strong>" + item.label + "</strong>, " + item.countryname + "</div>");
}
return li.appendTo(ul);
};
Upvotes: 0
Views: 61
Reputation: 30893
An example of how to disable a selection item is found here: http://jqueryui.com/autocomplete/#categories
This example is a bit complex, since we're accessing the menu widget inside the autocomplete widget. For your code, a similar method can be used:
$("#sl").autocomplete("widget").menu("option", "items", "> li:not('.no-select')");
widget()
Returns a jQuery object containing the menu element. Although the menu items are constantly created and destroyed, the menu element itself is created during initialization and is constantly reused.
This addresses point #1.
To address point #2, you need to consider the logic of assuming a selection if the user has not made a selection. For example, if the user typed in l
and got 10 results, or even just 2 results... which do you select for the user? Also, if the user has navigated away from the field, autoselect would close it's menu and destroy the results.
In my opinion, it would be better to examine the hidden fields, if they are empty, prevent the form from being submitted and force the user to select an option, make it a required field.
$(function() {
var countries = [{
country: 1,
countryname: "UK",
label: "London",
value: 1
}, {
country: 1,
countryname: "UK",
label: "Manchester",
value: 2
}];
$('#sl').autocomplete({
source: countries,
select: function(event, ui) {
event.preventDefault();
if (ui.item.label === "No results found") {
$("#sl").val("");
return false;
}
$("#country").val(ui.item.country); // save selected id to hidden input
$("#city").val(ui.item.value); // save selected id to hidden input
$('#sl').val(ui.item.label + ', ' + ui.item.countryname)
},
focus: function(event, ui) {
event.preventDefault();
$('#sl').val(ui.item.label);
},
response: function(event, ui) {
if (!ui.content.length) {
var noResult = {
value: "",
label: 'No results found'
};
ui.content.push(noResult);
}
}
});
$("#sl").autocomplete("widget").menu("option", "items", "> li:not('.no-select')");
$("#sl").autocomplete("instance")._renderItem = function(ul, item) {
var li = $("<li>");
if (item.country == undefined) {
li.addClass("no-select").append(item.label);
} else {
li.append("<div><strong>" + item.label + "</strong>, " + item.countryname + "</div>");
}
return li.appendTo(ul);
}
$("form").submit(function(e) {
e.preventDefault();
console.log($(this).serialize());
if ($("#country").val() == "" || $("#city").val() == "") {
$("#sl").focus();
return false;
}
return true;
});
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="search-homepage-input">
<form>
<div class="col-md-9">
<input type="text" name="sl" class="form-control shop-input" max-length="50" placeholder="Eg. England, London, Manchester" id="sl" /> <span style="color: red; font-size: 65%;">* Required</span>
<input type="text" name="country" id="country" style="display: none;" />
<input type="text" name="city" id="city" style="display: none;" />
</div>
<div class="col-md-3">
<button type="submit" class="btn btn-homepage">Find Teams</button>
</div>
</form>
</div>
Hope that helps.
Upvotes: 1