Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,13 @@ These attributes are available to set on the `<input-dropdown>` directive.
* `input-class-name`: String. Sets the classname for the input element - e.g. form-control for bootstrap
* `input-name`: String. Sets the name attribute on the input element
* `input-required`: Boolean. Sets ng-required on the input element. If true the input will validate when the user has made a selection from the dropdown list.
* `disabled`: Boolean. Sets ng-disabled on the input element
* `selected-item`: Object, *required*. Used in the controller to read the user's selection. Can be set to null when created or equal to an item in the dropdown array to set the initial value for the input. Will update when the user selects an item from the list.
* `default-dropdown-items`: Array. An array of strings or object to show in the dropdown list. If objects, each object must have a property `readableName` which is what will show in the dropdown. If not set there will be no default list when the input field is empty and you'll need to pass a list based on the users input in the `filter-list-method`.
* `only-show-non-empty-dropdown`: Boolean. If not set or set to false there will show dropdown always even though the dropdown has no item.
* `filter-list-method`: Function. Called when user types in the input field. Must return a promise that resolves with an array to use as a new dropdown list. Must be set with a `userInput` paramater: `filter-list-method="methodToCall(userInput)"`.
* `item-selected-method`: Function. Called when user selects an item from the dropdown. Must be set with an `item` paramater: `item-selected-method="methodToCall(item)"`.
* `value-changed-method`: Function. Called when user changes text in the input field or selects an item from the dropdown. The function can be set with `value` and `from` parameters: `value-changed-method="methodToCall(value, from)"`.
* `allow-custom-input`: Boolean. Set to true to let user enter their own value instead of forcing an item from the dropdown list to be selected.

### Custom user input
Expand Down
30 changes: 25 additions & 5 deletions inputDropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ angular.module('inputDropdown', []).directive('inputDropdown', [function() {
'placeholder="{{inputPlaceholder}}"' +
'autocomplete="off"' +
'ng-model="inputValue"' +
'class="{{inputClassName}}"' +
'class="{{inputClassName}}"' +
'ng-required="inputRequired"' +
'ng-change="inputChange()"' +
'ng-focus="inputFocus()"' +
'ng-blur="inputBlur($event)"' +
'ng-disabled="disabled"' +
'input-dropdown-validator>' +
'<ul ng-show="dropdownVisible">' +
'<ul ng-show="dropdownVisible && dropdownItems && dropdownItems.length">' +
'<li ng-repeat="item in dropdownItems"' +
'ng-click="selectItem(item)"' +
'ng-mouseenter="setActive($index)"' +
Expand All @@ -32,14 +33,17 @@ angular.module('inputDropdown', []).directive('inputDropdown', [function() {
selectedItem: '=',
allowCustomInput: '=',
inputRequired: '=',
disabled: '=',
inputName: '@',
inputClassName: '@',
inputPlaceholder: '@',
onlyShowNonEmptyDropdown: '@',
filterListMethod: '&',
valueChangedMethod: '&',
itemSelectedMethod: '&'
},
template: templateString,
controller: function($scope) {
controller: ["$scope", function($scope) {
this.getSelectedItem = function() {
return $scope.selectedItem;
};
Expand All @@ -52,7 +56,7 @@ angular.module('inputDropdown', []).directive('inputDropdown', [function() {
this.getInput = function() {
return $scope.inputValue;
};
},
}],
link: function(scope, element) {
var pressedDropdown = false;
var inputScope = element.find('input').isolateScope();
Expand Down Expand Up @@ -108,6 +112,8 @@ angular.module('inputDropdown', []).directive('inputDropdown', [function() {
scope.selectedItem = null;
showDropdown();

fireValueChangedEvent(scope.inputValue, 'input');

if (!scope.inputValue) {
scope.dropdownItems = scope.defaultDropdownItems || [];
return;
Expand Down Expand Up @@ -154,12 +160,17 @@ angular.module('inputDropdown', []).directive('inputDropdown', [function() {
hideDropdown();
scope.dropdownItems = [item];

fireValueChangedEvent(item, 'select');

if (scope.itemSelectedMethod) {
scope.itemSelectedMethod({item: item});
}
};

var showDropdown = function () {
if (scope.onlyShowNonEmptyDropdown && !(scope.dropdownItems && scope.dropdownItems.length)) {
return;
}
scope.dropdownVisible = true;
};
var hideDropdown = function() {
Expand Down Expand Up @@ -192,6 +203,15 @@ angular.module('inputDropdown', []).directive('inputDropdown', [function() {
}
};

var fireValueChangedEvent = function(value, from) {
if (scope.valueChangedMethod) {
scope.valueChangedMethod({
value: value,
from: from
})
}
};

element.bind("keydown keypress", function (event) {
switch (event.which) {
case 38: //up
Expand All @@ -208,7 +228,7 @@ angular.module('inputDropdown', []).directive('inputDropdown', [function() {
}
break;
case 9: // tab
if (scope.dropdownVisible && scope.dropdownItems && scope.dropdownItems.length > 0 && scope.activeItemIndex !== -1) {
if (scope.dropdownVisible && scope.dropdownItems && scope.dropdownItems.length > 0 && scope.activeItemIndex !== -1) {
scope.$apply(selectActiveItem);
}
break;
Expand Down