Angular-UI-Bootstrap自动补全文本框三项定制需求求解
定制Angular-UI-Bootstrap自动补全文本框的实现方案
嘿,我来帮你搞定这三个定制需求!咱们一步步调整你的现有代码,把每个功能都实现到位:
需求1:选中列表项时触发事件
Angular UI Bootstrap的typeahead组件专门提供了typeahead-on-select属性,用来处理选中项的回调——比直接用ng-change更精准,毕竟ng-change会在输入过程中就触发,而我们只需要选中项时执行逻辑。
你需要在input标签上添加这个属性,然后在控制器里定义对应的处理函数:
<input type="text" ng-model="selected" uib-typeahead="state.businessName as state.businessName for state in states | filter:$viewValue" typeahead-on-select="onItemSelected($item, $model, $label)" class="form-control">
控制器里补充回调函数:
$scope.onItemSelected = function(item, model, label) { // 这里写你选中项后要执行的逻辑,比如打印选中的企业信息 console.log('选中了:', item.businessName); // 如果需要关联ng-change的原有逻辑,也可以在这里调用对应的函数 };
需求2:未找到匹配项时显示“创建新项”
我们可以自定义一个过滤函数,当现有列表过滤后没有结果时,手动添加一个“创建新项”的选项,同时标记它方便后续处理:
首先在控制器里添加过滤函数:
$scope.filterStates = function(query) { // 先过滤现有企业列表 var filtered = $scope.states.filter(function(state) { return state.businessName.toLowerCase().includes(query ? query.toLowerCase() : ''); }); // 如果没有匹配结果且输入了内容,添加创建新项选项 if (filtered.length === 0 && query) { filtered.push({ businessName: '创建新项', isNew: true }); } return filtered; };
然后修改input的typeahead数据源为这个自定义函数:
<input type="text" ng-model="selected" uib-typeahead="state.businessName as state.businessName for state in filterStates($viewValue)" typeahead-on-select="onItemSelected($item, $model, $label)" class="form-control">
最后在回调函数里区分是否是新项:
$scope.onItemSelected = function(item, model, label) { if (item.isNew) { // 处理创建新项的逻辑,比如弹出创建表单或跳转页面 console.log('要创建新项,输入内容为:', $scope.selected); // 可以清空输入框方便后续操作 $scope.selected = ''; } else { // 处理选中已有项的逻辑 console.log('选中的企业:', item); } };
需求3:获得焦点/点击时显示全部列表项
我们可以通过uib-typeahead-is-open属性控制下拉框的显示状态,结合ng-focus和ng-click事件,在触发时清空查询条件并展开全部列表:
控制器里添加控制变量和触发函数:
$scope.isTypeaheadOpen = false; $scope.openTypeahead = function() { // 清空查询条件,确保显示全部列表 $scope.selected = ''; // 手动打开下拉框 $scope.isTypeaheadOpen = true; };
修改input标签绑定相关属性:
<input type="text" ng-model="selected" uib-typeahead="state.businessName as state.businessName for state in filterStates($viewValue)" typeahead-on-select="onItemSelected($item, $model, $label)" uib-typeahead-is-open="isTypeaheadOpen" ng-focus="openTypeahead()" ng-click="openTypeahead()" class="form-control">
完整修改后的代码
HTML部分
<div ng-controller="TypeaheadCtrl"> <input type="text" ng-model="selected" uib-typeahead="state.businessName as state.businessName for state in filterStates($viewValue)" typeahead-on-select="onItemSelected($item, $model, $label)" uib-typeahead-is-open="isTypeaheadOpen" ng-focus="openTypeahead()" ng-click="openTypeahead()" class="form-control"> </div>
JavaScript部分
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']); angular.module('ui.bootstrap.demo').controller('TypeaheadCtrl', function($scope, $http) { var _selected; $scope.selected = undefined; $scope.isTypeaheadOpen = false; $scope.states = [ { "@type":"CR", "companyId":1819, "companyCode":"NVX", "legalName":"Navex", "dbaName":"Navex Inc.", "formation":"P", "firstName":null, "middleName":null, "lastName":null, "dob":null, "registeredAgent":{ "personId":2, "category":null, "firstName":"Arthur", "middleName":"Parho", "lastName":"Benjiman", "dob":null, "addresses":null, "contacts":null, "fullName":"Benjiman, Arthur" }, "filingDate":null, "filingNo":null, "documentNumber":null, "ssn":null, "ein":null, "internal":true, "business":{ "code":"CR", "value":"Carrier" }, "locations":[ { "id":1821, "landmark":"4104 Banner Dr.", "type":{ "code":"P", "value":"Physical" }, "street1":"4104 Banner Dr.", "street2":null, "city":"Houston", "state":"TX", "zip":"77550", "country":null, "latitude":null, "longitude":null, "contacts":[ ], "action":0 } ], "mcNumber":"124578", "dotunitSeries":"111", "billingMethod":null, "businessName":"Navex" }, { "@type":"SH", "companyId":1824, "companyCode":null, "legalName":null, "dbaName":null, "formation":"I", "firstName":"Sikandar", "middleName":"", "lastName":"Ali", "dob":"05/01/2018", "registeredAgent":null, "filingDate":null, "filingNo":null, "documentNumber":null, "ssn":124578963, "ein":null, "internal":true, "business":{ "code":"SH", "value":"Shipper" }, "locations":[ { "id":1825, "landmark":"2202 Jennifer St", "type":{ "code":"P", "value":"Physical" }, "street1":"2202 Jennifer St", "street2":null, "city":"Dallas", "state":"TX", "zip":"77880", "country":null, "latitude":null, "longitude":null, "contacts":[ { "id":1826, "medium":{ "code":"EM", "value":"Email" }, "serviceLocator":"sikandarali744@gmail.com", "prefered":true, "action":0 } ], "action":0 } ], "dotunitSeries":null, "billingMethod":null, "mcNumber":null, "businessName":"Ali, Sikandar" }, { "@type":"TS", "companyId":1827, "companyCode":"", "legalName":"Wayis", "dbaName":"", "formation":"C", "firstName":null, "middleName":null, "lastName":null, "dob":null, "registeredAgent":null, "filingDate":null, "filingNo":null, "documentNumber":null, "ssn":null, "ein":null, "internal":true, "business":{ "code":"TS", "value":"Truck Stop" }, "locations":[ { "id":1828, "landmark":"2001 Ravi St", "type":{ "code":"P", "value":"Physical" }, "street1":"2001 Ravi St", "street2":null, "city":"Dallas", "state":"HI", "zip":"12345", "country":null, "latitude":null, "longitude":null, "contacts":[ ], "action":0 } ], "dotunitSeries":null, "billingMethod":null, "mcNumber":null, "businessName":"Wayis" }, { "@type":"BR", "companyId":1871, "companyCode":"", "legalName":"E2 Financial", "dbaName":"E2F", "formation":"C", "firstName":null, "middleName":null, "lastName":null, "dob":null, "registeredAgent":null, "filingDate":null, "filingNo":null, "documentNumber":null, "ssn":null, "ein":null, "internal":false, "business":{ "code":"BR", "value":"Broker" }, "locations":null, "mcNumber":"124578", "billingMethod":"MCS", "dotunitSeries":null, "businessName":"E2 Financial" } ]; // 自定义过滤函数,添加创建新项选项 $scope.filterStates = function(query) { var filtered = $scope.states.filter(function(state) { return state.businessName.toLowerCase().includes(query ? query.toLowerCase() : ''); }); if (filtered.length === 0 && query) { filtered.push({ businessName: '创建新项', isNew: true }); } return filtered; }; // 选中项的回调函数 $scope.onItemSelected = function(item, model, label) { if (item.isNew) { console.log('准备创建新项,输入内容为:', $scope.selected); // 这里可以添加你的创建逻辑,比如打开模态框 $scope.selected = ''; } else { console.log('选中的企业:', item); // 这里添加选中现有项的处理逻辑 } }; // 打开typeahead下拉框,显示全部列表 $scope.openTypeahead = function() { $scope.selected = ''; $scope.isTypeaheadOpen = true; }; // 保留你原有的其他代码 $scope.getLocation = function(val) { return $http.get('//maps.googleapis.com/maps/api/geocode/json', { params: { address: val, sensor: false } }).then(function(response){ return response.data.results.map(function(item){ return item.formatted_address; }); }); }; $scope.ngModelOptionsSelected = function(value) { if (arguments.length) { _selected = value; } else { return _selected; } }; $scope.modelOptions = { debounce: { default: 500, blur: 250 }, getterSetter: true }; $scope.statesWithFlags = [{'name':'Alabama','flag':'5/5c/Flag_of_Alabama.svg/45px-Flag_of_Alabama.svg.png'},{'name':'Alaska','flag':'e/e6/Flag_of_Alaska.svg/43px-Flag_of_Alaska.svg.png'},{'name':'Arizona','flag':'9/9d/Flag_of_Arizona.svg/45px-Flag_of_Arizona.svg.png'},{'name':'Arkansas','flag':'9/9d/Flag_of_Arkansas.svg/45px-Flag_of_Arkansas.svg.png'},{'name':'California','flag':'0/01/Flag_of_California.svg/45px-Flag_of_California.svg.png'},{'name':'Colorado','flag':'4/46/Flag_of_Colorado.svg/45px-Flag_of_Colorado.svg.png'},{'name':'Connecticut','flag':'9/96/Flag_of_Connecticut.svg/39px-Flag_of_Con'}]; });
内容的提问来源于stack exchange,提问作者Sikandar Sahab
相关产品推荐
相关产品推荐

