0

I'm trying to make an input with an autocomplete with any field value, so I created a custom pipe.

My question is how can I do this because I have a component that displays my json data and another component that contains the autocomplete input?

should I use the @Input and @Output decorators?

I'm quite a beginner I don't know how to do it

thank you very much for your help

json.file

 {
        "boatType": "Semi-rigide",
        "img": "/assets/img/boat-img/semi-rigide.jpg",
        "longeur": 10,
        "largeur": 20,
        "tirantEau": 50,
        "equipage": false,
        "annexe": true
    },

table.component.html

<div class="search">
    <app-input #inputComponent></app-input>
</div>
<table>
   <caption>Statement Summary</caption>
    <thead>
        <tr>
            <th scope="col" class="toto">img</th>
            <th scope="col">Type de bateau</th>
            <th scope="col">longeur</th>
            <th scope="col">largeur</th>
            <th scope="col">tirant d'eau</th>
            <th scope="col">equipage</th>
            <th scope="col">annexe</th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="let boat of user | filter : inputComponent?.searchText">
            <td data-label="img"><img [src]="boat.img" alt="boat" class="img"></td>
            <td data-label="boat type">{{ boat.boatType }}</td>
            <td data-label="longeur">{{boat.longeur}} cm</td>
            <td data-label="largeur">{{boat.largeur}} cm</td>
            <td data-label="tirant d'eau">{{boat.tirantEau}} cm</td>
            <td data-label="equipage">{{boat.equipage ? "Oui" : "Non"}}</td>
            <td data-label="annexe">{{boat.annexe ? "Oui" : "Non"}}</td>
        </tr>
    </tbody>
</table>

input.component.html

 <input type="text" placeholder="Chercher un bateau.." [(ngModel)]="searchText">

filter.pipe

     import { Pipe, PipeTransform } from '@angular/core';
        
        @Pipe({
          name: 'filter'
        })
        export class FilterPipe implements PipeTransform {
        
        transform(items: any[], searchText: string): any[] {
    if (!items) return [];
    if (!searchText) return items;

    // TODO: need to improve this filter
    // because at this moment, only filter by boatType
    return items.filter(item => {
      return item.boatType.toLowerCase().includes(searchText.toLowerCase());
    });
  }
        
        }

1 Answer 1

1

The code needs some changes because you're using the tools in an incorrect way.

However, I refactored a little and I got the code to work.

A brief explanation and here the solution on stackblitz: https://stackblitz.com/edit/angular-ivy-ybubhx?file=src/app/filter.pipe.ts

I had to take the search input reference from app-input component using #inputComponent. (There are other ways to get this).

app.component.html

<div class="search">
  <!-- I create a variable on template called inputComponent -->
  <app-input #inputComponent></app-input> 
</div>
<table>
  <caption>Statement Summary</caption>
  <thead>
    <tr>
      <th scope="col">type</th>
      <!-- <th scope="col" class="toto">img</th> -->
      <th scope="col">longeur</th>
      <th scope="col">largeur</th>
      <th scope="col">tirant d'eau</th>
      <th scope="col">equipage</th>
      <th scope="col">annexe</th>
    </tr>
  </thead>
  <body>
    <!-- I pass the searchText string taken from inputComponent to our filter pipe -->
    <tr *ngFor="let boat of boats | filter : inputComponent?.searchText">
      <!-- <td data-label="img"><img [src]="boat.img" alt="boat" class="img"></td> -->
      <td data-label="boat type">{{ boat.boatType }}</td>
      <td data-label="longeur">{{boat.longeur}} cm</td>
      <td data-label="largeur">{{boat.largeur}} cm</td>
      <td data-label="tirant d'eau">{{boat.tirantEau}} cm</td>
      <td data-label="equipage">{{boat.equipage ? "Oui" : "Non"}}</td>
      <td data-label="annexe">{{boat.annexe ? "Oui" : "Non"}}</td>
    </tr>
  </tbody>
</table>

app.component.ts

import { Component, VERSION } from "@angular/core";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  // I use boats as payload to demonstrate the filter pipe functionality
  boats = [
    {
      boatType: "a1a12",
      img: "/assets/img/boat-img/semi-rigide.jpg",
      longeur: 10,
      largeur: 20,
      tirantEau: 50,
      equipage: false,
      annexe: true
    },
    {
      boatType: "EAEA",
      img: "/assets/img/boat-img/eaea.jpg",
      longeur: 10,
      largeur: 20,
      tirantEau: 50,
      equipage: false,
      annexe: true
    },
    {
      boatType: "bcbc",
      img: "/assets/img/boat-img/bcbc.jpg",
      longeur: 10,
      largeur: 20,
      tirantEau: 50,
      equipage: false,
      annexe: true
    },
    {
      boatType: "bcbc 2",
      img: "/assets/img/boat-img/bcbc.jpg",
      longeur: 10,
      largeur: 20,
      tirantEau: 50,
      equipage: false,
      annexe: true
    }
  ];
}

input.component.ts

import { Component, Input } from "@angular/core";

@Component({
  selector: "app-input",
  template: `
    <input
      type="text"
      placeholder="Chercher un bateau.."
      [(ngModel)]="searchText"
    />
  `,
  styles: [
    `
      h1 {
        font-family: Lato;
      }
    `
  ]
})
export class InputComponent {
  searchText: string;
}

filter.pipe.ts


import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name: "filter"
})
export class FilterPipe implements PipeTransform {
  transform(items: any[], searchText: string): any[] {
    if (!items) return [];
    if (!searchText) return items;

    // TODO: need to improve this filter
    // because at this moment, only filter by boatType
    return items.filter(item => {
      return item.boatType.toLowerCase().includes(searchText.toLowerCase());
    });
  }
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.