-1

i am new in angular 12, I created a search input and a list of static data, and I decided to write a pipe to filter the data when I search something, So after I added the pipe inside the ngFor I got an error that says : Error: src/app/template/ui/pages/courses/courses.component.html:23:78 - error TS2339: Property 'query' does not exist on type 'CoursesComponent'.

23       <div class="col-12 col-lg-4" *ngFor="let item  of data | searchFilter: query ">
                                                                                ~~~~~

  src/app/template/ui/pages/courses/courses.component.ts:13:16
    13   templateUrl: './courses.component.html',
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~
    The error occurs in the template of component CoursesComponent.

So I checked the existing answers here but none speaking about Pipe and NgModel so here's my pipe:

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

@Pipe({
    name: 'searchFilterPipe'
})

export class SearchFilterPipe implements PipeTransform {

    transform(value: any, args?: any): any {
        if(!value) return null;
        if(!args) return value;
  
        args = args.toLowerCase();
  
        return value.filter(function(data: any){
            return JSON.stringify(data).toLowerCase().includes(args);
        });
    }

}

Here my view:

 <form action="">
              <div class="input-group mb-4 border rounded-pill p-1">
                <input id="searchInputtwo" type="search"  [(ngModel)]="query" placeholder="What're you searching for?" aria-describedby="button-addon3" class="form-control bg-none border-0" >
                <div class="input-group-append border-0">
                  <button id="button-addon3" type="submit" class="btn btn-link text-dark"><i class="fa fa-search"></i></button>
                </div>
              </div>
            </form>
          </div>
    </div>
    <div class="row" id="lessonList">
      <div class="col-12 col-lg-4" *ngFor="let item  of data | searchFilter: query ">
        <div class="card mb-4 mb-lg-0 border-secondary shadow">
          <img src="{{item.image}}" alt="Animations CSS modernes" class="card-img-top">
          <div class="card-body">
            <h5 class="card-title">{{ item.title }}</h5>
            <p class="card-text">{{item.text}}</p>
            <a href="courses/details/{{item.id}}" class="btn btn-info btn--start ">Démarrer l'apprentissage</a>
          </div>
        </div>
      </div>

Here my Ts file:

import { Component, Input, OnInit, NgModule } from '@angular/core';    
import { chapterModel } from 'src/app/core/models/chapter.model';
import { competencesModel } from 
 'src/app/core/models/competences.model';
import { CourseModel } from 'src/app/core/models/course.model';
import { preriquisiteModel } from 
'src/app/core/models/preriquisite.model';
import { teacherModel } from 'src/app/core/models/teacher.model';
import { SearchService } from 'src/app/core/services/search.service';


@Component({
  selector: 'app-courses',
  templateUrl: './courses.component.html',
  styleUrls: ['./courses.component.scss']
})
export class CoursesComponent implements OnInit {

  public searchFilter: any = '';
  public data:CourseModel[];

  constructor(private searchService: SearchService) {
    this.data = [
      new CourseModel(1,"Créez des animations CSS","Vous allez plonger dans le monde des animations CSS pour donner vie à vos pages web !",
      [new chapterModel(1,"coo","text")],false,
      [new preriquisiteModel(2,"Programmation JavaScript","Programmation JavaScript","Learn Java Script !")],
       [ new competencesModel("Savoir Faire des animations")], [ new teacherModel(52,"Laura DuFont") ],
       "assets/images/lessons/css.jpeg"),

       new CourseModel(2,"Programmer avec JavaScript","Ce cours est conçu pour vous enseigner les bases du langage de programmation JavaScript.",
       [new chapterModel(1,"coo","text")],false,
       [new preriquisiteModel(1,"Programmation html/css","Programmation html/css","Learn Html/Css !")],
        [ new competencesModel("Savoir le language Java Script")], [ new teacherModel(53,"Will Alexander") ],
        "assets/images/lessons/js.jpeg"),

        new CourseModel(3,"Les fondamentaux de Swift","Découvrez le développement iOS et réalisez des applications taillées pour l'iPhone et l'iPad !",
        [new chapterModel(1,"coo","text")],false,
        [new preriquisiteModel(2,"Programmation ","Programmation ","Learn Swift !")],
         [ new competencesModel("Savoir programmer pour Iphone et Ipad")], [ new teacherModel(54,"Jamie Sutherland") ],
         "assets/images/lessons/swift.jpeg"),
    ];
   }

  ngOnInit(): void {
  
  }

 searchForm(){
   this.searchService.searchAndFilterCourses(this.searchFilter);
   console.log(this.searchFilter);

   }

}

I took this code from a tutorial of Angular 9 but I don't know if my angular 12 needs a different syntax or not.

My goal is to find a solution for this problem and make the solution available for all possible future victims of this error.

1 Answers1

0

When you're using [(ngModel)] you are binding the value of the input field to a property inside your component's TS file. In your case you have [(ngModel)]="query" which means it's expecting the property query to exist.

But in your TS file you only have searchFilter and data defined. Add public query = ''; and it should no longer give you the error.

Also, you shouldn't need to setup a pipe unless you're planning to use this filtering logic many times across your app. If it's only happening in this component, you should keep the filtering logic in the component's TS file.

Joshua McCarthy
  • 1,739
  • 1
  • 9
  • 6
  • Ah no , i think the pipe i took from the tutorial make the data initially disappear , the data will appear again only if i write something in the text input , yes i use a pipe because im planning to use the same logic in a lot of places, can you help me to normalize the pipe function to make it stop making data disappear before i write something in the input box? thank you in advance for your solution – Road to engineering Jul 20 '21 at 00:38
  • i think it is not working well at all , i have to press on the route two times to get the view displaying , i think the solution of pipe brings up a lot of the problem to the app since i tried it , there have to be some alternatives – Road to engineering Jul 20 '21 at 00:45
  • when i deleted ngModel the problem is gone! but the problem is how to get the value of input without ngModel? – Road to engineering Jul 20 '21 at 00:55
  • You can use template reference, but I disagree to put this code into the component because pipe memoize the return for the equals parameters when you call and don't executed everytime – Jonathan Lopez Jul 20 '21 at 01:28
  • Perhaps a stackblitz link would help because from what I see in your example, nothing would be working. You do not have `query` defined in your TS file. You're declaring the pipe `searchFilterPipe` but you never use it. Your template is trying to use a pipe `searchFilter` which is a local property that is an empty string. And lastly, we're unable to see the logic in the `SearchService` file. – Joshua McCarthy Jul 20 '21 at 02:02