3
votes

I'm using an custom pipe to filter my data by city
And then I display the first 5 results using the slice pipe

My problem is that I would like to know how many results I got in total, before the slice pipe

Is there an method to "send" the count from the pipe to the component and then update the view with the new value?

My component looks like this:

import { Component, OnInit, Input } from '@angular/core';
import { CategoryPipe } from './category-filter.pipe';
import { Router } from '@angular/router';
import { CategoryService } from './category-page.service';
import { CategoryData } from './category.model';

@Component({
  selector: 'app-category-page',
  templateUrl: './category-page.component.html',
  styleUrls: ['./category-page.component.scss'],
  providers: [CategoryPipe]
})

export class CategoryComponent implements OnInit {
  @Input() propertyCountFromFilter: number;
  categoryData: CategoryData[];
  public cityId = 0;

  constructor(
    public categoryService: CategoryService,
    private router: Router) { }

  propertyLimit = 5;
  ngOnInit() {
    this.router.routeReuseStrategy.shouldReuseRoute = function () {
      return false;
    };
    this.categoryService.getPropertyData()
      .then(result => this.categoryData = JSON.parse(result))
      .then(result => this.propertyCountFromFilter = this.categoryData.length)
      .catch(error => console.log(error));
  }
}

Pipe:

import { PipeTransform, Pipe, Output, EventEmitter } from '@angular/core';
import { CategoryData } from './category.model';

@Pipe({
    name: 'categoryPipe',
    pure: false
})

export class CategoryPipe implements PipeTransform {
    constructor() { }

    @Output() propertyCountFromFilter: number;
    change: EventEmitter<number> = new EventEmitter<number>();
    transform(input: CategoryData[], cityId?: number): CategoryData[] {
        console.log('run');
        if (input) {
            this.propertyCountFromFilter = input.length;
            if (input.length === 0) {
                return input;
            }
            input = input.filter(data => data.LocationId === cityId);
        }
        return input;
    }
}

View:

  <div>Total number of properties: <span id="propertyCount">{{propertyCountFromFilter}}</span></div>
  <div class="property" *ngFor="let property of categoryData | categoryPipe: cityId | slice:0:propertyLimit">
    <h3 class="property-header">
      {{property.Title}}
    </h3>
  </div>

I'm trying to get the "propertyCountFromFilter" value from the pipe to the component, but the view is not updated

I could use this to update the view, but the problem is that I'm using ssr and the DOM is not available when I run the code:

document.getElementById('propertyCount').innerHTML = this.propertyCountFromFilter.toString();

If I use categoryData.length I will only get the number of properties set in the slice pipe

2

2 Answers

1
votes

You are able to pass as many arguments to the pipe as you want. So, one of the solutions could be using this additional argument as some tracker for changes. Unfortunately, as JS will copy primitive values by value, you'll need to pass an object for example with property count.

I've created the raw example for you here: https://codesandbox.io/s/xoz9214694

So by using this approach, you could create such a connection with a pipe. I'd try even EventEmitter instead of a simple object.

1
votes

You can remove the pipe slice and using javascript. then you have in categoryData.lenght the count of your data

<div class="property" *ngFor="let property of categoryData.slice(0,propertyLimit) | categoryPipe: cityId">
    <h3 class="property-header">
      {{property.Title}}
    </h3>
  </div>
There are {{categoryData.length}} cities