2016-04-14 4 views
1

Ich versuche, eine Suchleitung für Angular 2 zu erstellen. Es sollte ein verschachteltes Objekt und filtern Sie die Objekte, die einen Suchbegriff entsprechen. Ich habe eine Basisversion funktioniert, aber ich habe zwei Probleme kennengelernt.Wie filtere ich ein JavaScript-Objekt, wenn ich eine Such-Pipe mit eckiger 2 mache?

Problem 1 ist, dass ich jetzt Schlüsselnamen hart codieren muss oder verwenden, was mir wie ein schmutziger Hack mit JSON.stringify scheint.

Was ist eine elegantere Art, das Objekt zu filtern, indem man den Begriff mit einem beliebigen Wert abgleicht, außer einer Liste hartkodierter Objekte wie _id und url?

Problem zwei ist, dass, wenn die Zeichenfolge term ein Leerzeichen enthält, möchte ich es teilen und filtern die obj mit beiden Begriffen. Ich kann es unter Verwendung terms = term.split(' '); teilen.

Aber wie kann ich Filtern mit mehreren Begriffen erreichen?

Mein aktueller Code:

import {Pipe} from 'angular2/core'; 

@Pipe({ 
    name: "search" 
}) 
export class SearchPipe{ 
    transform(obj: any, [term]) { 
     if (obj != null && term) { 
      return obj.filter(el => { 

       //var test = JSON.stringify(el); 
       //return test.toLowerCase().includes(term.toLowerCase()); //trows a compile error but seems to work. 

       return el.name.toLowerCase().includes(term.toLowerCase()) || el.place.toLowerCase().includes(term.toLowerCase()) || el.title.toLowerCase().includes(term.toLowerCase()) ; 

      }); 

     } else { 
      return obj; 
     } 
    } 
} 

Erwartete Eingabeformat:

[ 
{ 
    "_id": "56ffbe512ba199777d51c6ae", 
    "picture": "http://placehold.it/36x36", 
    "name": "Melissa Reeves", 
    "company": "Orbixtar", 
    "place": "Greenwich, Belarus", 
    "title": "voluptate est ipsum", 
    "location": { 
    "lat": -78.926961, 
    "lng": 90.157653 
    }, 
    "url": "http://lol.lol" 
}, 
{ 
    "_id": "56ffbe5119cf66e94b3800b4", 
    "picture": "http://placehold.it/36x36", 
    "name": "Chelsea Lindsay", 
    "company": "Squish", 
    "place": "Vowinckel, Belarus", 
    "title": "anim ea exercitation", 
    "location": { 
    "lat": 66.547582, 
    "lng": 162.720388 
    }, 
    "url": "http://lol.lol" 
} 
] 

Wenn der Begriff "term1" ist, ich möchte, dass es Objekte zurückzugeben, die "term1" enthält.

Wenn andererseits "term1 term2 term3""term1 term2 term3" ist, möchte ich für alle Objekte zurückgeben, die alle Begriffe enthalten, aber nicht unbedingt in dieser bestimmten Reihenfolge.

Als Beispiel.

Der Begriff "Melissa" sollte das erste Objekt zurückgeben.

Der Begriff "Melissa Belarus" sollte auch nur das erste Objekt zurückgeben. Obwohl das zweite Objekt mit einem der Schlüssel übereinstimmt.

+0

Bevorzugen '(el) => {' 'über Funktion (el) {' den Umfang der 'this' mit der Klasse zu halten, statt der Funktion. –

+0

Können Sie bitte ein Beispiel hinzufügen, wie das Ergebnis für einen konkreten Begriff genau aussehen soll? –

+0

Vielen Dank, dass Sie darauf hingewiesen haben. Es ist gut zu wissen. Ich habe ein Beispiel für den Begriff hinzugefügt. – zAPF

Antwort

1

Versuchen Sie, diese (ungetestet)

@Pipe({ 
    name: "search" 
}) 
export class SearchPipe{ 
    transform(obj: any, [term]) { 
    if (obj != null && term) { 
     return obj.filter(el => { 

     var test = JSON.parse(JSON.stringify(el)); 
     delete test['url']; 
     delete test['_id']; 

     var testString = JSON.stringify(test); 

     Object.keys(test).forEach(k => { 
      testString = testString.replace(k, ''); 
     }); 

     let terms = term.replace(/[\s]+/gm, " ").replace(/^[\s]|[\s]$/gm, "").split(' '); 
     let containCount = 0; 

     terms.forEach(t => { 
      if(testString.toLowerCase().indexOf(t.toLowerCase()) > -1) 
      { 
      ++containCount; 
      } 
     }); 

     return (containCount == terms.length); 
     }); 

    } else { 
     return obj; 
    } 
    } 
} 
+0

Dies funktioniert für einen Begriff mit einigen Änderungen. indexOf gibt nicht immer "true" zurück, also muss für '! == -1' getestet werden, das zweite Problem ist, dass beim Aufteilen der Zeichenkette ein leerer Wert an der Stelle steht, an der das Leerzeichen steht. wie in '[" term1 ",," term2 "]' löste ich dies mit 'let newArray = []; für (var i = 0; i zAPF

+0

Das dritte Problem mit dieser Lösung ist, dass nicht beide Begriffe übereinstimmen, gibt es Objekte zurück, die einen der Begriffe entsprechen. was ist nicht mein erwünschtes Ergebnis. Vielen Dank, dass Sie sich die Zeit genommen haben :) – zAPF

+0

Meine schlechte ... um Ihre Anforderung klar zu verstehen, würde es einige weitere Informationen über gewünschte Eingabe und Ausgabe benötigen .... Das ist nichts. –

Verwandte Themen