Angular JS – Focaliza automaticamente a input e mostra o menu suspenso typeahead – ui.bootstrap.typeahead

Estou usando o Angular JS – ui.bootstrap.typeahead:

Gostaria de clicar em um botão e focar um campo de input e mostrar automaticamente a lista suspensa de sugestão de headers. Eu tenho uma diretiva que foca automaticamente o campo de input quando o botão é clicado. Como posso mostrar o menu suspenso automaticamente para que o usuário possa usar a seta para baixo ou clicar para escolher rapidamente um usuário?

Eu criei um Plunker com o arquivo JS bootstrap editável para mexer:

http://plnkr.co/edit/Z79LY0OYlwFc3wirjxol?p=preview

Este é meu script completo:

         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(); }); } }); } }; }); function TypeaheadCtrl($scope, $http) { $scope.selected = undefined; $scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming']; $scope.opened = false; $scope.open = function() { $scope.opened = true; } $scope.close = function() { $scope.opened = false; } }  

How can I open the typeahead dropdown automatically when button is pressed?

I have a directive that automatically focuses on the field but I can't seem to automatically show the typeahead. Even adding down arrow key click support would be great.




Model: {{selected | json}}

Como HarishR mencionou em um comentário, ainda não há suporte embutido para esse recurso.

Mas eu só quero tentar hacking e aqui está o resultado: http://plnkr.co/edit/Qrnat8yTvISuM1qHHDlA?p=preview

Ele contém muitos hacks para fazer isso funcionar:

  1. include jQuery para usar o .trigger (), pode ser replace pelo JS nativo, mas eu sou preguiçoso.
  2. use ng-focus para chamar .trigger (‘input’) para acionar o popup typehead
  3. use ng-trim = “false” para desabilitar o ajuste automático do valor da input
  4. uma diretiva typeahead personalizada vazia que interage com o controlador ngModel para aplicar a lógica secretEmptyKey para ignorar a verificação typeahead-min-length:

     .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 }); } } }) 
  5. uma function comparadora de filtro personalizada que sempre retorna true (mostra todos os resultados) quando um argumento é o secretEmptyKey:

     $scope.stateComparator = function (state, viewValue) { return viewValue === secretEmptyKey || (''+state).toLowerCase().indexOf((''+viewValue).toLowerCase()) > -1; }; 
  6. remover o limitePara filtrar para mostrar todos os resultados

  7. definir propriedades css max-height e overflow para mostrar a barra de rolagem se o conteúdo for muito longo

Feito!

Atualizada:

Eu adicionei a diretiva ao github para atualizações e access fáceis. Agora você pode instalá-lo como uma dependência através do bower.

Postagem original:

Eu criei um hack bastante limpo que não requer nenhuma mudança para o ui-bootstrap-tpls . A idéia é usar $ setViewValue () para acionar o pop-up com uma combinação de uma function comparadora de filtro especial.

Para contornar a verificação minLength , $ setViewValue () deve ser definido com um valor maior que 1, então estou usando uma string de espaço. O papel da function comparadora é tratar um espaço como uma correspondência para todos os itens, para que todos apareçam ao clicar em uma input vazia.

Eu criei uma diretiva simples:

 angular.module('app') .directive('typeaheadFocus', function () { return { require: 'ngModel', link: function (scope, element, attr, ngModel) { //trigger the popup on 'click' because 'focus' //is also triggered after the item selection element.bind('click', function () { var viewValue = ngModel.$viewValue; //restore to null value so that the typeahead can detect a change if (ngModel.$viewValue == ' ') { ngModel.$setViewValue(null); } //force trigger the popup ngModel.$setViewValue(' '); //set the actual value in case there was already a value in the input ngModel.$setViewValue(viewValue || ' '); }); //compare function that treats the empty space as a match scope.emptyOrMatch = function (actual, expected) { if (expected == ' ') { return true; } return actual.indexOf(expected) > -1; }; } }; }); 

Uso:

  

Eu tenho uma solução de trabalho, alterando alguns códigos em ui-bootstrap-tpls-0.10.0.js. Portanto, não há diferenças na marcação html typeahead.

Você pode dar uma olhada aqui em http://plnkr.co/edit/LXHDpL?p=preview .

Para usar essa correção, use o ui-bootstrap-tpls-0.10.0.js do Plunk. Para ver minhas alterações, abra o ui-bootstrap-tpls-0.10.0.js do Plunk e procure por ‘ahneo’.

  1. //minimal no of characters that needs to be entered before typeahead kicks-in // ahneo :: before //var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1; // ahneo :: after (changed minimal no of characters to 0 by default) var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 0; 2. // ahneo :: new (set input value to empty string if it contains " " string value) if (inputValue === ' ') { inputValue = ''; modelCtrl.$setViewValue(''); } 3. // ahneo :: before //if (inputValue && inputValue.length >= minSearch) { // ahneo :: after (add new condition to get matches for min search = 0) if (minSearch === 0 || inputValue && inputValue.length >= minSearch) { 4. // ahneo :: new (bind element to focus event to trigger modelCtrl.$parsers.unshift method) element.bind('focus', function (evt) { if (modelCtrl.$viewValue === '') { modelCtrl.$setViewValue(' '); } }); 

Espero que isto ajude

Agora, como não tenho reputação suficiente para comentar, devo escrever uma nova resposta para alertar as pessoas sobre a resposta da runTarm acima. Esta é uma solução viável, mas corre o risco de incorrer no seguinte erro:

 Error: [$rootScope:inprog] $apply already in progress 

Isso parece ser devido ao fato de o ng-focus ser um evento sincronizado ( veja a discussão aqui ). Em vez disso, pode-se usar o atributo ng-click e esse erro não ocorre.

Além disso, verifiquei que

 $element.triggerHandler('input'); 

funciona tão bem quanto o gatilho jQuery na resposta do runTarm.

Parece que o suporte embutido para este recurso está chegando em uma versão futura na forma de valor de suporte do atributo typeahead-min-length de 0.

Ele é implementado neste commit na ramificação principal https://github.com/angular-ui/bootstrap/commit/d859f42cc022a5d8779f1c7b358486bbdd04ed57 , mas ainda não há lançamento com isso e ele não está na ramificação 0.14.x.

Espero que uma nova versão chegue rapidamente, para que não haja mais necessidade dessas soluções alternativas.

Eu queria algo parecido com a descrição do OP e a única solução que encontrei foi criar um modelo que combina as diretivas de menu suspenso e digitação antecipada – talvez o OP ou outra pessoa ache útil:

 angular.module('app', ['ui.bootstrap']) .controller('AppCtrl', function($scope) { $scope.model; $scope.options = [{label:'Option 1'}, {label:'Option 2'}, {label:'Option 3'}]; $scope.onSelect = function($item, $model, $label) { $scope.model = angular.copy($item); } }); 
     

Eu resolvi esse problema por meio de uma diretiva. Quando você usa essa diretiva, mostra a lista sem algum filtro, então você digita sua pesquisa para encontrar um elemento.

 angular.module('myapp') .directive('typeaheadLikeSelect', ['$parse',function($parse) { return { require: 'ngModel', link: function (scope, element, attr, ngModel){ var aux_modelValue, aux_viewValue, modelGetter = $parse(attr.ngModel), modelSetter = modelGetter.assign; var noViewValue = function(){ return ngModel.$$lastCommittedViewValue === undefined || !ngModel.$$lastCommittedViewValue.trim(); }; var forceEvent = function(){ ngModel.$setViewValue(); ngModel.$viewValue = ' '; ngModel.$setViewValue(' '); ngModel.$render(); scope.$apply(); element.val(element.val().trim()); }; element.on('mousedown', function(e){ e.stopPropagation(); forceEvent(); }); element.on('blur', function(e){ e.stopPropagation(); if(aux_modelValue){ modelSetter(scope, aux_modelValue); scope.$apply(); } }); scope.$watch(function () { return ngModel.$modelValue; }, function(newValue, oldValue){ if(newValue || (!newValue && !oldValue)) aux_modelValue = newValue; }); } }; }]); 

Deixo um código de visão, para testar o código acima.

  
No Results Found

typeahead-min-length = “0” faz o truque (estou usando v0.4.0)

Eu queria que o typeahead fosse aberto sempre que meu elemento de input tivesse foco. A solução do @ yohairosen não funcionou para mim na versão mais recente do Angular Bootstrap (Versão: 1.0.3). Aqui está a solução que funcionou para mim. Envolvia invocar manualmente o analisador anexado pelo ui-bootstrap-typeahead que preenche as sugestões:

 angular.module('app') .directive('typeaheadFocus', function () { return { require: 'ngModel', link: function (scope, element, attr, ngModel) { element.bind('click', function () { ngModel.$parsers[0](ngModel.$viewValue); }); } }; }; }); 

O que queremos é triggersr (‘input’) no elemento de input quando estiver focado.

A maneira correta de fazê-lo em Angular é fazê-lo em uma diretiva.

 angular.module('app') .directive('showList', function() { return { restrict: 'A', link: function(scope, iEle) { iEle.focus(function() { iEle.trigger('input'); }); } }; }); 

Use esta diretiva no elemento de input typeahead –

  

você pode conseguir por este código

  $scope.change = function() { var e = document.getElementById("test"); var $e = angular.element(e); $e.triggerHandler('focus'); $e.triggerHandler('input'); } 

altere o teste para o seu ID de cabeça de tipo