2
respostas

Empaquei!!!!

Prezados, segui o vídeo, fiz todas as etapas até chegar à implementação do OnInit do SearchComponent, fiz conforme o vídeo e a descrição, porém, ao testar o filtro no navegador, não funciona... Não sei onde estou errando, já assisti aos vídeos 2x e continuo sem saber o que aconteceu, os servidores estão rodando, e não aparece nenhum erro, nem no log do navegador e nem no servidor do angular. Seguem classes:

import { Component, OnInit, OnDestroy, Output, EventEmitter, Input } from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';

@Component({
    selector: 'ap-search',
    templateUrl: './search.component.html'
})
export class SearchComponent implements OnInit, OnDestroy {

    @Output() onTyping: EventEmitter<string> = new EventEmitter<string>();
    @Input() value: string = '';
    debounce: Subject<string> = new Subject<string>();

    ngOnDestroy(): void {
        this.debounce
            .pipe(debounceTime(300))
            .subscribe(filter => console.log(filter));
    }
    ngOnInit(): void {
        this.debounce.unsubscribe;
    }

}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { PhotoListComponent } from './photo-list.component';
import { PhotosComponent } from './photos/photos.component';
import { LoadButtonComponent } from './load-button/load-button.component';
import { FilterByDescription } from './filter-by-description';
import { PhotoModule } from '../photo/photo.module';
import { CardModule } from 'src/app/shared/components/card/card.module';
import { SearchComponent } from './search/search.component';

@NgModule({
    declarations: [
        PhotoListComponent,
        PhotosComponent,
        LoadButtonComponent,
        FilterByDescription,
        SearchComponent
    ],
    imports: [ 
        CommonModule,
        PhotoModule,
        CardModule
    ]
})
export class PhotoListModule {

}
<ap-search></ap-search>

<ap-photos 
    [photos]="photos | filterByDescription: filter">
</ap-photos>

<ap-load-button 
    (click)="load()" 
    [hasMore]="hasMore">
</ap-load-button>
import { Component, OnInit } from '@angular/core';

import { Photo } from '../photo/photo';
import { ActivatedRoute } from '@angular/router';
import { PhotoService } from '../photo/photo.service';

@Component({
  selector: 'ap-photo-list',
  templateUrl: './photo-list.component.html',
  styleUrls: ['./photo-list.component.css']
})
export class PhotoListComponent implements OnInit {
  photos: Photo[] = [];
  filter: string = '';
  hasMore: boolean = true;
  currentPage: number = 1;
  userName: string = '';

  constructor(
    private photoService: PhotoService,
    private activatedRoute: ActivatedRoute
  ) { }

  ngOnInit(): void {
    this.userName = this.activatedRoute.snapshot.params.userName;
    this.photos = this.activatedRoute.snapshot.data['photos'];
  }

  load(): void {
    this.photoService
      .listFromUserPaginated(this.userName, ++this.currentPage)
      .subscribe(photos => {
        this.photos = this.photos.concat(photos);
        if (!photos.length) this.hasMore = false;
      })
  }
}
<div class="text-center mt-3 mb-3">
    <form>
        <i aria-hidden="true" class="fa fa-search mr-1"></i>
        <input
            class="rounded"
            type="search"
            placeholder="search..."
            autofocus
            (keyup)="debounce.next($event.target.value)"
            [value]=value>
    </form>
</div>

Desde já agradeço.

2 respostas

Concluí a aula 7 e mesmo assim não consegui fazer o filtro funcionar, a aplicação não apresenta nenhum tipo de erro, e botão Load more não limpa o campo Search, ou seja, a comunicação entre os componentes não está ocorrendo, realmente não sei o que houve, e não consigo encontrar meu erro. Seguem mais classes:

<ap-search 
    (onTyping)="filter = $event"
    [value]="filter">
</ap-search>

<ap-photos 
    [photos]="photos | filterByDescription: filter">
</ap-photos>

<ap-load-button 
    (click)="load()" 
    [hasMore]="hasMore">
</ap-load-button>
<div class="text-center mt-3 mb-3">
    <form>
        <i aria-hidden="true" class="fa fa-search mr-1"></i>
        <input
            class="rounded"
            type="search"
            placeholder="search..."
            autofocus
            (keyup)="debounce.next($event.target.value)"
            [value]="value">
    </form>
</div>
import { Component, OnInit, OnDestroy, Output, EventEmitter, Input } from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';

@Component({
    selector: 'ap-search',
    templateUrl: './search.component.html'
})
export class SearchComponent implements OnInit, OnDestroy {

    @Output() onTyping = new EventEmitter<string>();
    @Input() value: string = '';
    debounce = new Subject<string>();

    ngOnDestroy(): void {
        this.debounce
            .pipe(debounceTime(300))
            .subscribe(filter => this.onTyping.emit(filter));
    }
    ngOnInit(): void {
        this.debounce.unsubscribe;
    }

}
import { Component, OnInit } from '@angular/core';

import { Photo } from '../photo/photo';
import { ActivatedRoute } from '@angular/router';
import { PhotoService } from '../photo/photo.service';

@Component({
  selector: 'ap-photo-list',
  templateUrl: './photo-list.component.html',
  styleUrls: ['./photo-list.component.css']
})
export class PhotoListComponent implements OnInit {
  photos: Photo[] = [];
  filter: string = '';
  hasMore: boolean = true;
  currentPage: number = 1;
  userName: string = '';

  constructor(
    private photoService: PhotoService,
    private activatedRoute: ActivatedRoute
  ) { }

  ngOnInit(): void {
    this.userName = this.activatedRoute.snapshot.params.userName;
    this.photos = this.activatedRoute.snapshot.data['photos'];
  }

  load(): void {
    this.photoService
      .listFromUserPaginated(this.userName, ++this.currentPage)
      .subscribe(photos => {
        this.filter = '';
        this.photos = this.photos.concat(photos);
        if (!photos.length) this.hasMore = false;
      })
  }
}
<div class="text-center" *ngIf="hasMore; else messageTemplate">
    <button class="btn btn-primary">Load more</button>
</div>

<ng-template #messageTemplate>
    <p class="text-center text-muted">No more data to load</p>
</ng-template>
import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'ap-load-button',
  templateUrl: './load-button.component.html',
  styleUrls: ['./load-button.component.css']
})
export class LoadButtonComponent implements OnInit {

  @Input() hasMore: boolean = false;

  constructor() { }

  ngOnInit(): void {
  }

}
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { PhotoListComponent } from './photo-list.component';
import { PhotosComponent } from './photos/photos.component';
import { LoadButtonComponent } from './load-button/load-button.component';
import { FilterByDescription } from './filter-by-description';
import { PhotoModule } from '../photo/photo.module';
import { CardModule } from 'src/app/shared/components/card/card.module';
import { SearchComponent } from './search/search.component';

@NgModule({
    declarations: [
        PhotoListComponent,
        PhotosComponent,
        LoadButtonComponent,
        FilterByDescription,
        SearchComponent
    ],
    imports: [ 
        CommonModule,
        PhotoModule,
        CardModule
    ]
})
export class PhotoListModule { }

Oi, Leandro, tudo bem?

Poderia disponibilizar o teu código no github para que possamos analisa-lo melhor? Porque baixamos o seu projeto como está e podemos testar e ver os erros mais facilmente. Aguardo :}