Reputation: 19425
So I have two autocomplete containers. Instead of writing code twice, I will use the same autocomplete call.
But in order to triger correct autocomplete (read: populate correct result list), I need to assign it to a variable. I've done this a long time ago, but I have forgotten how I did it.
So I have the following:
autocomplete: function () {
var autocompleteInput = null;
var autocompleteResultList = null;
$('.autocomplete').on("input", function (e) { // I have 2 of these
autocompleteInput = $(this); // This is the input i'm working with
autocompleteResultList = autocompleteInput.closest('.autocomplete-result');
resourcesData(autocompleteInput.val());
}).on('focus', function (e) {
autocompleteInput.val(''); //Cannot read property 'val' of null
}).on('blur', function (e) {
autocompleteResultList.removeClass('is-active');
});
}
My HTML x 2 (short version)
<div class="autocomplete-wrapper">
<input class="autocomplete" type="text" >
<input class="resource-id" type="hidden">
<div class="autocomplete-result"></div>
</div>
I'm pretty sure it' some basic jQuery knowledge in regards of setting a variable = a jQuery object (autocompleteInput = $(this);
) and how it all works that I've forgotten.
Any help appreciated :)
PS. I'm not using jQuery autocomplete - I've made my own.
Upvotes: 2
Views: 119
Reputation: 19425
So after good help from Patric, Baao and Trincot (and others), I got it working. So just want to share my working solution just incase others are facing similar issues. It's probably not the most elegant solution, but it's working :)
let resources = {
init: function () {
this.searchResources();
},
searchResources: function () {
var self = this;
$('.autocomplete').on("input", function (e) {
let term = $(this).val();
if(term.length > 1){
self.autocomplete($(this));
}
}).on('focus', function (e) {
$(this).val('');
}).on('blur', function (e) {
$(this).closest('.autocomplete-result').removeClass('is-active');
});
},
autocomplete: function(obj){
let url = 'http://localhost.no:8080/resources%TERM';
url = url.replace('%TERM', '/' + $(obj).val() );
var resultList = $(obj).siblings('.autocomplete-result');
let source = $('#autocomplete-list').html();
let template = Handlebars.compile (source);
$.ajax({
method: "GET",
url: url,
dataType: "json",
success: function(result) {
let content = template({resources: result.data});
$(resultList).html(content);
$('.autocomplete-list-item').on('click', function (e) {
$(obj).siblings('input.resource-id').val($(this).data('resource-id'));
$(obj).val($(this).data('resource-name'));
$(resultList).removeClass('is-active');
console.log($(this).data('resource-id'));
console.log($(this).data('resource-name'));
});
},
error: function(err){console.log(err);}
}).done(function () {
var resultList = $(obj).siblings('.autocomplete-result');
if(!$(resultList).hasClass('is-active')){
$(resultList).addClass('is-active')
}
});
}
};
One of my input fields looks like this:
<div class="input-field column is-6 autocomplete-wrapper">
<input id="autocomplete-owner" class="autocomplete" autocomplete="off" type="text" >
<label for="autocomplete-owen">Prosjektleder</label>
<input id="resource-id-owner" class="resource-id" type="hidden" name="resource-id-owner">
<div class="autocomplete-result"></div>
</div>
Upvotes: 0
Reputation: 350202
You have to abandon the variables that you share across the different event callbacks. But since they are easy to derive, just do that in each event handler itself.
Some things to note:
closest
method only looks to parents, not to siblings, so use the siblings
method instead (or if your structure is slightly different than in your question, maybe .closest(".autocomplete-wrapper").find(".autocomplete-result")
).resourcesData
is currently not provided with any information about where it should populate the data, so you should pass it an extra argument for it to know where to populate, and deal with that argument in that function.Suggested code would then be:
autocomplete: function () {
$('.autocomplete').on("input", function (e) {
// extra argument
resourcesData($(this).val(), $(this).siblings('.autocomplete-result'));
}).on('focus', function (e) {
$(this).val('');
}).on('blur', function (e) {
$(this).siblings('.autocomplete-result').removeClass('is-active');
});
}
Upvotes: 3