2013-08-25 16 views
19

La funzionalità typeahead nell'interfaccia utente di AngularJs sembra semplice e potente, tuttavia, ho cercato di capire come ottenere la corrispondenza sui caratteri principali. Ad esempio, se digito "A" nella casella di input mi piacerebbe vedere tutti gli stati che iniziano con "A" e non tutti gli stati che contengono una "A" nel nome. Ho cercato per un paio di giorni su questo e sembra che Angular abbia il concetto di un filtro personalizzato che ha un 'comparatore' I documenti su questo hanno un semplice esempio che non mostra la sintassi esatta per l'implementazione di un comparatoreAngularJs UI typeahead corrisponde ai caratteri principali

L'html è simile a questo :

<div>Selected: <span>{{selected}}</span></div> 
    <div><input type="text" ng-model="selected" typeahead="name for name in states | filter:selected"></div> 

Il javascript di base assomiglia a questo

angular.module('firstChar', ['ui.bootstrap']); 

    function TypeaheadCtrl($scope) { 
     $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']; 
    } 

Ho un plunker qui http://plnkr.co/edit/LT6pAnS8asnpFEd5e6Ri

Quindi la sfida in breve è far sì che il typeahead AngularUI corrisponda solo ai personaggi principali.

Qualsiasi aiuto o idea su questo sarebbe molto apprezzato.

risposta

49

Alla fine della giornata la tua domanda non è propriamente specifica della direttiva typeahead ma ha più a che fare con il funzionamento dei filtri AngularJS.

Prima di presentare una soluzione di lavoro, tenere presente che la direttiva typeahead fa un uso pesante dell'infrastruttura AngularJS ($ http, promises) e del linguaggio delle espressioni. Quindi è importante rendersi conto che lo states | filter:selected non è altro che un'espressione AngularJS.

Dando un'occhiata all'espressione di cui sopra abbiamo bisogno di trovare un modo di filtrando un array per restituire un elenco di elementi corrispondenti. L'unica cosa speciale della direttiva typeahead è che esiste una variabile $viewValue che rappresenta un valore inserito da un utente nella casella di input. Quindi, in pratica, è sufficiente filtrare l'array states per restituire gli articoli che iniziano con $viewValue.

Ci sono molti modi per farlo, ma dal momento che hai menzionato il comparatore per i filtri (tieni presente che sono stati introdotti solo nella versione 1.1.x di AngularJS) dovresti definire una funzione di confronto che dovrebbe decidere se un l'articolo dato deve essere restituito nell'elenco dei risultati oppure no. Tale funzione potrebbe apparire come segue:

$scope.startsWith = function(state, viewValue) { 
    return state.substr(0, viewValue.length).toLowerCase() == viewValue.toLowerCase(); 
} 

Averlo definito l'utilizzo è molto semplice:

typeahead="name for name in states | filter:$viewValue:startsWith" 

Ecco la Plunk di lavoro: http://plnkr.co/edit/WWWEwU4oPxvbN84fmAl0?p=preview

+0

WOW ! Grazie! Sembra funzionare perfettamente. Fornisce un bell'esempio dei concetti e la sintassi concatenata di Angular. –

+0

Una domanda però ... Come definiamo lo 'stato' nella funzione startsWith? Mi rendo conto che sta iterando attraverso gli stati, ma come fa a venire il nome/oggetto 'stato'. Sto cercando di utilizzare questo codice in un esempio più realistico e non funziona. –

+0

La risposta alla mia domanda è che 'stato' nell'esempio è il valore corrente dell'array utilizzato per compilare l'elenco typeahead. Il mio problema è che sto usando un oggetto per popolare il typeahead in modo da poter ottenere l''id' per il valore selezionato. Angolare itera attraverso l'oggetto e passa ciascuno dei membri dell'oggetto alla funzione di confronto per eseguire il confronto tra stringhe. –

0

Filtro personalizzato per ottenere la corrispondenza di essere fatto sui personaggi principali nella casella di completamento automatico del tipo.

(function() { 
 

 
    // Create global filters using angular.filter() only. Never use local filters inside 
 
    // controllers/services. This enhances testing and reusability. 
 
    function xpTypeaheadFilter() { 
 
      return function(items, props) { 
 

 
      var out = []; 
 
      
 
      if (angular.isArray(items)) { 
 

 
       items.forEach(function(item) { 
 
       
 
       
 

 

 
       var text = props.toLowerCase(); 
 
       var itemLoverCase =item.toLowerCase(); 
 
       var substr = itemLoverCase.substr(0, text.length); 
 

 
        
 
       if (substr === text) { 
 
        
 
        out.push(item); 
 
         
 
       } 
 
       
 

 
       }); 
 
      } else { 
 
       // Let the output be the input untouched 
 
       out = items; 
 
      } 
 
      console.log("out lem", out.length); 
 

 
      return out; 
 
      }; 
 
    } 
 

 
    // Pass functions into module methods rather than assigning a callback. 
 
    // This helps aid with readability and helps reduced the amount of code "wrapped" 
 
    // inside Angular. 
 
    angular.module('common') 
 
    .filter('xpTypeaheadFilter', xpTypeaheadFilter); 
 
})();
<input type="text" ng-model="vesselName" placeholder="Vessel Name" typeahead="vesselName for vesselName in vesselNames | xpTypeaheadFilter:$viewValue | limitTo:8" class="form-control form-textbox" >

+0

Non c'è alcuna opzione direttiva per far funzionare questo? – wanttobeprofessional

0

ho appena messaggio modificato contrassegnato come rispose e funziona quando la lista sta avendo Id e titolo sia:

<input type="text" ng-model="ledgerstatementModel.Supplier" typeahead="supplier as supplier.Name for supplier in supplierList | filter:{Name:$viewValue}:startsWith" class="form-control"> 

e in js:

$scope.startsWith = function (supplier, viewValue) { 
     return supplier.substr(0, viewValue.length).toLowerCase() == viewValue.toLowerCase(); 
    } 
Problemi correlati