Skip to content

Instantly share code, notes, and snippets.

@tkh44
Last active April 5, 2022 11:56
Show Gist options
  • Select an option

  • Save tkh44/11235101 to your computer and use it in GitHub Desktop.

Select an option

Save tkh44/11235101 to your computer and use it in GitHub Desktop.
Small autocomplete directive for Angular.
<input type="text"/>
<div>Searching: {{searching}}</div>
<ul>
<li ng-transclude
ng-repeat="item in items"
ng-click="selectItem(item)">
</li>
<li ng-show="showNoResults">No results</li>
</ul>
angular.module('iOffice.autocomplete', [])
.directive('autocomplete', ($http) => {
return {
restrict: 'EA',
require: '?ngModel',
transclude: true,
templateUrl: function(tElement, tAttrs) {
if (tAttrs.templateUrl === undefined) {
return '/directives/autocomplete/autocomplete.html'
} else {
return tAttrs.templateUrl;
}
},
scope: {
autocompleteOptions: '&'
},
link: ($scope, $element, attrs, ngModel) => {
var $input = $element.find('input'),
options = {},
httpOptions = {},
selecting = false; // Flag if user is selecting or not
_.defaults($scope.autocompleteOptions() || {}, {
delay: 350,
ajax: {},
query: 'search'
});
httpOptions = _.defaults(options.ajax, {
method: 'GET',
url: options.url
});
httpOptions.params = _.defaults(httpOptions.params, {
search: ''
});
var getData = (query) => {
httpOptions.params[options.query] = query;
$scope.searching = true;
$http(httpOptions).success((data, status, headers, config) => {
if (_.isEmpty(data)) {
reset();
} else {
$scope.items = data;
}
$scope.showNoResults = _.isEmpty(data);
}).error(err => {
console.log(err);
}).then(() => {
$scope.searching = false;
});
};
var onKeyup = (e) => {
var query = $.trim(e.target.value);
selecting = true;
if (query.length) {
getData(query);
} else {
$scope.$apply(() => {
reset();
});
}
};
var onKeydown = (e) => {
// Backspace runs backthrough search
if (e.keyCode === 8) {
selecting = true;
ngModel.$setViewValue();
}
};
var reset = () => {
$scope.items = [];
};
// Parses what is going to be set to model
ngModel.$parsers.push(function (fromView) {
if (selecting) {
return undefined;
}
return angular.copy(fromView);
});
$input.on('keyup', _.debounce(onKeyup, options.delay));
$input.on('keydown', onKeydown);
$scope.items = [];
$scope.showNoResults = false;
$scope.selectItem = (item) => {
var inputValue = item[options.displayKey];
if (inputValue) {
selecting = false;
$input.val(inputValue);
ngModel.$setViewValue(item);
}
reset();
}
}
};
});
class ContactFormCtrl {
constructor(credentialsService) {
this.credentialsService = credentialsService;
this.selectedUser = null;
this.options = {
displayKey: 'name', // Item[displayKey] will be used to fill input value upon selection
queryParam: 'search', // query parameter used to denote search term ( "someurl.com?search=")
delay: 250, // Keyup debounce delay in ms
url: credentialsService(address) + '/external/api/v2/users', //url to recieve data from
ajax: { // $http configuration https://docs.angularjs.org/api/ng/service/$http
params: {
selector: 'name,phone,mobile,email,room(floor(building))'
},
headers: {
'x_auth_username': credentialsService(username),
'x_auth_password': credentialsService(password)
}
}
};
}
}
ContactFormCtrl.$inject = ['credentialsService'];
app.controller('ContactFormCtrl', ContactFormCtrl);
<div ng-controller="ContactFormCtrl as contactForm">
<autocomplete ng-model="contactForm.selectedUser" autocomplete-options="contactForm.options">
<span>{{item.id}} | {{item.name}}</span>
</autocomplete>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment