AngularJS [typeahead] 在 onFocus 上重新打开结果下拉菜单
AngularJS [typeahead] reopen result dropdown on onFocus
我在 typeahead 中的以下用例中遇到问题:
问题:
- 用户开始输入,下拉菜单打开并显示结果
- 用户点击输入字段外(输入字段中没有删除任何内容),下拉菜单关闭
- 用户点击返回输入框(并没有开始输入任何内容)但没有任何反应。 → 期望的行为是:下拉列表再次打开并显示与上次相同的结果列表(当然,只有在输入字段中有任何内容时才会发生)
- 当用户搜索任何内容时,如果找到结果并发生焦点丢失并且字符串不会再次被清除,焦点什么都没有发生,没有提示
- 当用户搜索任何内容时,如果未找到结果并发生焦点丢失,字符串将被清除,并且还会出现未找到数据的消息。
所以,故事的寓意是,在第一种情况下,如果字符串不是从列表中选择的,并且它是列表字符串的子字符串,则应该清除它...
那么,也许是预先输入焦点搜索设置?
HTML:
<input type="text" focus-me="opened" ng-focus="onFocus($event)" ng-show="opened" ng-trim="false" ng-model="selected" empty-typeahead typeahead="state for state in states | filter:$viewValue:stateComparator" class="form-control" />
JS:
(function () {
var secretEmptyKey = '[$empty$]'
angular.module('plunker', ['ui.bootstrap'])
.directive('focusMe', function($timeout, $parse) {
return {
//scope: true, // optionally create a child scope
link: function(scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function(value) {
if(value === true) {
$timeout(function() {
element[0].focus();
});
}
});
}
};
})
.directive('emptyTypeahead', function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, modelCtrl) {
// this parser run before typeahead's parser
modelCtrl.$parsers.unshift(function (inputValue) {
var value = (inputValue ? inputValue : secretEmptyKey); // replace empty string with secretEmptyKey to bypass typeahead-min-length check
modelCtrl.$viewValue = value; // this $viewValue must match the inputValue pass to typehead directive
return value;
});
// this parser run after typeahead's parser
modelCtrl.$parsers.push(function (inputValue) {
return inputValue === secretEmptyKey ? '' : inputValue; // set the secretEmptyKey back to empty string
});
}
}
})
.controller('TypeaheadCtrl', function($scope, $http, $timeout) {
$scope.selected = undefined;
$scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Wyoming'];
$scope.opened = true;
$scope.stateComparator = function (state, viewValue) {
return viewValue === secretEmptyKey || (''+state).toLowerCase().indexOf((''+viewValue).toLowerCase()) > -1;
};
$scope.onFocus = function (e) {
$timeout(function () {
$(e.target).trigger('input');
$(e.target).trigger('change'); // for IE
});
};
});
}());
我有这个 Plunker 来展示我的代码的样子。
还有GitHub Issue.
您需要检查模糊输入值是否存在于列表中。
为此,请执行以下操作:
在输入中添加属性ng-blur="onBlur($event)"
并在您的控制器中定义以下方法:
$scope.onBlur = function (e) {
$timeout(function () {
var val = $(e.target).val();
if(val && $scope.states.indexOf(val) == -1) {
$(e.target).val("")
}
});
};
大家好,
经过一番努力,我得到了正确的解决方案...
有一些指令可用于解决方案,
在typeaheadFocus
指令中添加以上条件,
if ((e.type == "focus" && viewValue != ' ') && (e.type == "focus" && viewValue != '')){
return;
}
在typeaheadFocus
指令和typeaheadOnDownArrow
指令中添加如下函数,
//compare function that treats the empty space as a match
scope.$emptyOrView = function(actual) {
if(ngModel.$viewValue.trim()) {
return actual ? actual.value.toString().toLowerCase().indexOf(ngModel.$viewValue.toLowerCase()) > -1 : false;
}
return true;
};
在ui-bootstrap.js中更改此条件,
if (inputFormatter) {
locals.$model = modelValue;
if(modelValue){
locals.$label = view_value;
} else {
locals.$label = '';
}
在ui-bootstrapjs中添加如下event
,
element.bind('blur', function(evt) {
hasFocus = false;
if (!isEditable && modelCtrl.$error.editable) {
element.val('');
modelCtrl.$viewValue = ' ';
}
if(!isEditable && scope.no_data_found) {
//ngModel.$viewValue = '';
modelCtrl.$viewValue = ' ';
scope.no_data_found = false;
popUpEl.find('.typeaheadNoData').remove();
resetMatches();
scope.$digest();
element.val("");
}
});
在ui-bootstrap.js,
中添加这个
// I listen for emptyTypeAhead events from the parent scope chain.
originalScope.$on(
"emptyTypeAhead",
function handlePingEvent( event, newVal1) {
var scope = originalScope.$new();
modelCtrl.$setViewValue(newVal1);
return newVal1;
}
);
在所有指令中添加ui-bootstrap.js以上函数,
.directive('shouldFocus', function($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch(attrs.shouldFocus, function(newVal, oldVal) {
var isActive = scope.$eval(attrs.shouldFocus);
if(isActive) {
var ele = element[0];
var parent = ele.parentNode
if(ele.offsetTop + ele.offsetHeight > parent.offsetHeight + parent.scrollTop){
parent.scrollTop = ele.offsetTop;
} else if(parent.scrollTop > ele.offsetTop) {
parent.scrollTop = ele.offsetTop;
}
}
});
}
}
});
示例:
<input type="text" ng-model="inquiry.account"
placeholder="Select Account"
typeahead="account.id as account.text for account in account_typeahead_json"
typeahead-input-formatter="formatModel($model,$label)"
typeahead-editable="false" typeahead-on-down-arrow typeahead-focus />
希望这个回答对您有所帮助。
Here 我已经添加了 ui-bootstrap.js
我在 typeahead 中的以下用例中遇到问题:
问题:
- 用户开始输入,下拉菜单打开并显示结果
- 用户点击输入字段外(输入字段中没有删除任何内容),下拉菜单关闭
- 用户点击返回输入框(并没有开始输入任何内容)但没有任何反应。 → 期望的行为是:下拉列表再次打开并显示与上次相同的结果列表(当然,只有在输入字段中有任何内容时才会发生)
- 当用户搜索任何内容时,如果找到结果并发生焦点丢失并且字符串不会再次被清除,焦点什么都没有发生,没有提示
- 当用户搜索任何内容时,如果未找到结果并发生焦点丢失,字符串将被清除,并且还会出现未找到数据的消息。
所以,故事的寓意是,在第一种情况下,如果字符串不是从列表中选择的,并且它是列表字符串的子字符串,则应该清除它...
那么,也许是预先输入焦点搜索设置?
HTML:
<input type="text" focus-me="opened" ng-focus="onFocus($event)" ng-show="opened" ng-trim="false" ng-model="selected" empty-typeahead typeahead="state for state in states | filter:$viewValue:stateComparator" class="form-control" />
JS:
(function () {
var secretEmptyKey = '[$empty$]'
angular.module('plunker', ['ui.bootstrap'])
.directive('focusMe', function($timeout, $parse) {
return {
//scope: true, // optionally create a child scope
link: function(scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function(value) {
if(value === true) {
$timeout(function() {
element[0].focus();
});
}
});
}
};
})
.directive('emptyTypeahead', function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, modelCtrl) {
// this parser run before typeahead's parser
modelCtrl.$parsers.unshift(function (inputValue) {
var value = (inputValue ? inputValue : secretEmptyKey); // replace empty string with secretEmptyKey to bypass typeahead-min-length check
modelCtrl.$viewValue = value; // this $viewValue must match the inputValue pass to typehead directive
return value;
});
// this parser run after typeahead's parser
modelCtrl.$parsers.push(function (inputValue) {
return inputValue === secretEmptyKey ? '' : inputValue; // set the secretEmptyKey back to empty string
});
}
}
})
.controller('TypeaheadCtrl', function($scope, $http, $timeout) {
$scope.selected = undefined;
$scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Wyoming'];
$scope.opened = true;
$scope.stateComparator = function (state, viewValue) {
return viewValue === secretEmptyKey || (''+state).toLowerCase().indexOf((''+viewValue).toLowerCase()) > -1;
};
$scope.onFocus = function (e) {
$timeout(function () {
$(e.target).trigger('input');
$(e.target).trigger('change'); // for IE
});
};
});
}());
我有这个 Plunker 来展示我的代码的样子。
还有GitHub Issue.
您需要检查模糊输入值是否存在于列表中。 为此,请执行以下操作:
在输入中添加属性ng-blur="onBlur($event)"
并在您的控制器中定义以下方法:
$scope.onBlur = function (e) {
$timeout(function () {
var val = $(e.target).val();
if(val && $scope.states.indexOf(val) == -1) {
$(e.target).val("")
}
});
};
大家好,
经过一番努力,我得到了正确的解决方案...
有一些指令可用于解决方案,
在typeaheadFocus
指令中添加以上条件,
if ((e.type == "focus" && viewValue != ' ') && (e.type == "focus" && viewValue != '')){
return;
}
在typeaheadFocus
指令和typeaheadOnDownArrow
指令中添加如下函数,
//compare function that treats the empty space as a match
scope.$emptyOrView = function(actual) {
if(ngModel.$viewValue.trim()) {
return actual ? actual.value.toString().toLowerCase().indexOf(ngModel.$viewValue.toLowerCase()) > -1 : false;
}
return true;
};
在ui-bootstrap.js中更改此条件,
if (inputFormatter) {
locals.$model = modelValue;
if(modelValue){
locals.$label = view_value;
} else {
locals.$label = '';
}
在ui-bootstrapjs中添加如下event
,
element.bind('blur', function(evt) {
hasFocus = false;
if (!isEditable && modelCtrl.$error.editable) {
element.val('');
modelCtrl.$viewValue = ' ';
}
if(!isEditable && scope.no_data_found) {
//ngModel.$viewValue = '';
modelCtrl.$viewValue = ' ';
scope.no_data_found = false;
popUpEl.find('.typeaheadNoData').remove();
resetMatches();
scope.$digest();
element.val("");
}
});
在ui-bootstrap.js,
中添加这个 // I listen for emptyTypeAhead events from the parent scope chain.
originalScope.$on(
"emptyTypeAhead",
function handlePingEvent( event, newVal1) {
var scope = originalScope.$new();
modelCtrl.$setViewValue(newVal1);
return newVal1;
}
);
在所有指令中添加ui-bootstrap.js以上函数,
.directive('shouldFocus', function($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch(attrs.shouldFocus, function(newVal, oldVal) {
var isActive = scope.$eval(attrs.shouldFocus);
if(isActive) {
var ele = element[0];
var parent = ele.parentNode
if(ele.offsetTop + ele.offsetHeight > parent.offsetHeight + parent.scrollTop){
parent.scrollTop = ele.offsetTop;
} else if(parent.scrollTop > ele.offsetTop) {
parent.scrollTop = ele.offsetTop;
}
}
});
}
}
});
示例:
<input type="text" ng-model="inquiry.account"
placeholder="Select Account"
typeahead="account.id as account.text for account in account_typeahead_json"
typeahead-input-formatter="formatModel($model,$label)"
typeahead-editable="false" typeahead-on-down-arrow typeahead-focus />
希望这个回答对您有所帮助。