Angular JS – Attiva automaticamente l’input e mostra dropdown typeahead – ui.bootstrap.typeahead

Sto usando Angular JS – ui.bootstrap.typeahead:

Vorrei fare clic su un pulsante e mettere a fuoco un campo di input e mostrare automaticamente il menu a discesa suggerimento typeahead. Ho una direttiva che mette a fuoco automaticamente il campo di input quando si fa clic sul pulsante. Come posso visualizzare automaticamente il menu a discesa in modo che l’utente possa utilizzare la freccia giù o fare clic su per scegliere rapidamente un utente?

Ho creato un Plunker con il file JS di ui-bootstrap modificabile per armeggiare:

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

Questo è il mio copione 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}}

Come menzionato da HarishR in un commento, non esiste ancora un supporto integrato per questa funzione.

Ma voglio solo provare a fare hacking ed ecco il risultato: http://plnkr.co/edit/Qrnat8yTvISuM1qHHDlA?p=preview

Contiene molti hack per farlo funzionare:

  1. includere jQuery per usare .trigger (), potrebbe essere sostituito con JS nativo ma sono pigro.
  2. usa ng-focus per chiamare .trigger (‘input’) per triggersre il popup di tipo
  3. usa ng-trim = “false” per disabilitare il taglio automatico del valore di input
  4. una direttiva custom typeahead vuota che interagisce con il controller di ngModel per applicare la logica secretEmptyKey per aggirare il controllo 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. una funzione di confronto del filtro personalizzato che restituisce sempre true (mostra tutti i risultati) quando un argomento è secretEmptyKey:

     $scope.stateComparator = function (state, viewValue) { return viewValue === secretEmptyKey || (''+state).toLowerCase().indexOf((''+viewValue).toLowerCase()) > -1; }; 
  6. rimuovi il filtro limitTo per mostrare tutti i risultati

  7. imposta le proprietà css max-height e overflow per mostrare la barra di scorrimento se il contenuto è troppo lungo

Fatto!

aggiornato:

Ho aggiunto la direttiva a github per aggiornamenti e accesso semplici. Ora puoi installarlo come dipendenza tramite bower.

Post originale:

Ho trovato un hack abbastanza pulito che non richiede modifiche a ui-bootstrap-tpls . L’idea è di utilizzare $ setViewValue () per triggersre il popup con una combinazione di una speciale funzione di confronto del filtro.

Per bypassare il controllo minLength , $ setViewValue () deve essere impostato su un valore superiore a 1, quindi sto usando una stringa di spazio. Il ruolo della funzione di confronto è di trattare uno spazio come una corrispondenza a tutti gli elementi in modo che vengano visualizzati quando si fa clic su un input vuoto.

Ho creato una direttiva semplice:

 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:

  

Ho trovato una soluzione funzionante cambiando codice in ui-bootstrap-tpls-0.10.0.js. Quindi non ci sono differenze nel markup html typeahead.

Puoi dare un’occhiata qui su http://plnkr.co/edit/LXHDpL?p=preview .

Per utilizzare questa correzione, utilizzare ui-bootstrap-tpls-0.10.0.js dal Plunk. Per vedere le mie modifiche, apri ui-bootstrap-tpls-0.10.0.js dal Plunk e cerca “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(' '); } }); 

Spero che questo ti aiuti

Ora, poiché non ho abbastanza reputazione per commentare, devo scrivere una nuova risposta per avvisare la gente della risposta di RunTarm sopra. Questa è una soluzione valida, ma corre il rischio di incappare nel seguente errore:

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

Questo sembra essere dovuto al fatto che ng-focus è un evento sincronizzato ( vedi la discussione qui ). Invece, si può usare l’attributo ng-click e questo errore non si verifica.

Inoltre, l’ho verificato

 $element.triggerHandler('input'); 

funziona esattamente come il trigger jQuery nella risposta di runTarm.

Sembra che il supporto integrato per questa funzione sia disponibile in una versione imminente sotto forma di typeahead-min-length supporta il valore 0.

È implementato in questo commit nel ramo principale https://github.com/angular-ui/bootstrap/commit/d859f42cc022a5d8779f1c7b358486bbdd04ed57 , ma non è ancora stato rilasciato con questo e non è nel ramo 0.14.x.

Speriamo che una nuova versione arriverà rapidamente in modo che non ci sia più bisogno di questi rimedi.

Volevo qualcosa di simile alla descrizione dell’OP e l’unica soluzione che ho trovato è stata quella di creare un modello che combini il dropdown e le direttive typeahead – forse l’OP o qualcun altro lo troverà utile:

 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); } }); 
     

Ho risolto questo problema attraverso una direttiva. Quando si utilizza questa direttiva, mostra l’elenco senza alcun filtro, quindi si digita la ricerca per trovare un 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; }); } }; }]); 

Lascio un codice di visualizzazione, per testare il codice sopra.

  
No Results Found

typeahead-min-length = “0” fa il trucco (sto usando v0.4.0)

Volevo che il typeahead si aprisse ogni volta che il mio elemento di input era attivo. La soluzione di @yohairosen non ha funzionato per me sull’ultima versione di Angular Bootstrap (Versione 1.0.3). Ecco la soluzione che ha funzionato per me. Ha comportato il richiamo manuale del parser allegato da ui-bootstrap-typeahead che popola i suggerimenti:

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

Quello che vorremmo è innescare (‘input’) sull’elemento di input quando è focalizzato.

Il modo corretto di farlo in Angular è di farlo in una direttiva.

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

Usa questa direttiva sull’elemento di input typeahead –

  

puoi ottenere con questo codice

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

cambia il test con l’ID della tua testa-tipo