труба angular2 не работает - ошибок нет

У меня есть служба, которая возвращает список страниц. Теперь я хочу написать канал с именем pagesFilter, который возвращает список страниц, для которых этот ключ имеет значение true.

Затем я хочу применить этот фильтр при нажатии на элемент навигации.

Почему-то я не могу заставить его работать. Ошибок в консоли нет, переменная фильтра корректно обновляется. Любые советы приветствуются.

Мой HTML:

<!-- portfolio submenu -->
<div id="portfolioMenu">
    <div id="portfolioMenuOrangeLine"></div>
    <div id="filter1" class="miniNavButton" (click)="changeFilter('app demos')">
        <a>
            <svg class="icon icon-eye">
                    <use xlink:href="symbol-defs.svg#icon-eye"></use>
                </svg>
        </a>
    </div>
    <div id="filter2" class="miniNavButton" (click)="changeFilter('github repos')">
        <a>
            <svg class="icon icon-embed">
                    <use xlink:href="symbol-defs.svg#icon-embed"></use>
                </svg>
        </a>
    </div>
    <div id="filter3" class="miniNavButton" (click)="changeFilter('work in progress')">
        <a>
            <svg class="icon icon-hammer">
                    <use xlink:href="symbol-defs.svg#icon-hammer"></use>
                </svg>
        </a>
    </div>
</div>

<h2 class="filterHeading">Showing: {{ filter }}</h2>

<!-- portfolio content -->
<div class="portfolioContainer">
    <div class="displayHack"></div>
    <div *ngFor="#p of pages" class="portfolioPageContainer">
        <img [attr.src]="p.img" class="portfolioThumbnail">
        <h2>{{ p.name }}</h2>
        <a [attr.href]="p.repo">
            <div>
                <p>{{ p.description }}</p>
            </div>
            <p class="portfolioRepoLink">See the Code!</p>
        </a>
    </div>
    <div class="displayHack"></div>
</div>

обслуживание страниц:

import { Injectable } from 'angular2/core';

export class Page {
    constructor(public img: string, public name: string, public repo: string, public description: string, public demo: boolean, public github: boolean, public finished: boolean) { }
}

@Injectable()
export class PagesService {
    getPages() {
        return [
            new Page('./app/images/placeholder.png', 'veryNiceWords', 'https://github.com/Shooshte/veryNiceWords', 'A hobby app, made to enable posting, rating and sharing quotes over social networks. Work in progress.', false, true, false),
            new Page('./app/images/placeholder.png', 'ZIC IJS', 'https://github.com/Shooshte/ZIC', 'Refurbishing of on old library webpage with AngularJS.', false, true, false),
            new Page('./app/images/weather.png', 'Show the Local weather', 'http://codepen.io/shooshte/pen/NxOwOX', 'A freeCodeCamp exercise, designed to show the local weather.', true, false, true),
            new Page('./app/images/calculator.png', 'Calculator', 'http://codepen.io/shooshte/pen/qbjJdy', 'A freeCodeCamp exercise, which requires you to build a javascript calculator.', true, false, true),
            new Page('./app/images/github.png', 'MTGO Draft Replayer', 'https://github.com/Shooshte/MTGO-Draft-Replayer', 'A simple web app that opens a MTGO draft log file, and re-creates the draft from it.', false, true, false),
            new Page('./app/images/codeeval.png', 'codeEval', 'https://github.com/Shooshte/CodeEval', 'CodeEval challenges solutions written in javascript and posted to gitHub.', false, true, true)
        ];
    }
}

компонент портфолио (который использует сервис):

import { Component } from 'angular2/core';
import { ViewEncapsulation } from 'angular2/core';
import { Page, PagesService } from './pages.service';
import { Pipe, PipeTransform } from 'angular2/core';

@Pipe({ name: 'filter' })
export class pagesFilter {
    transform(pages, [key]): string {
        return pages.filter(page => {
            return page.hasOwnProperty(key);
        });
    }
}

@Component({
    selector: 'portfolio',
    templateUrl: '/app/views/portfolio.html',
    styleUrls: ['../app/styles/PortfolioMobile.css', '../app/styles/PortfolioOther.css'],
    pipes: [pagesFilter],
    encapsulation: ViewEncapsulation.None
})

export class PortfolioComponent {
    filter = 'everything';

    filterPortfolio(parameter:String) {
        return this.pages ? 'pagesFilter' : parameter
    }

    changeFilter(x) {
        this.filter = x;

        if (x == 'app demos') {
            this.filterPortfolio('demo');
        }
        else if (x == 'github repos') {
            this.filterPortfolio('repo');
        }
        else if (x == 'miniNavButton') {
            this.filterPortfolio('finished');
        }
    }

    pages: Page[];

    constructor(private _pagesService: PagesService) { }

    ngOnInit() {
        this.pages = this._pagesService.getPages();
    }

}

person Miha Šušteršič    schedule 20.04.2016    source источник
comment
Я не нашел использования pagesFilter, он должен быть в porfolio.html где он? Это должно выглядеть так, как Тьерри описал в ответе.   -  person Ankit Singh    schedule 20.04.2016
comment
функция changeFilter() вызывает this.FilterPortfolio, которая вызывает pagesFilter   -  person Miha Šušteršič    schedule 20.04.2016
comment
return this.pages ? 'pagesFilter' : parameter не вызывает pagesFilter , это просто строка, более того, pagesFilter не является функцией, это конвейер, который должен использоваться в template точно так же, как ответ Тьерри.   -  person Ankit Singh    schedule 20.04.2016


Ответы (2)


Вам нужно указать параметр для канала:

@Pipe ({
  name:'filter'
})
export class FilterPipe {
  transform(value, params) {
    var filter = params[0];

    return value.filter((item)=> {
      // for example
      return (item.name === filter);
    });
  }
}

Вы можете использовать этот канал таким образом, основываясь на вводе формы и свойстве компонента:

@Component({
  (...)
  template: `
    <form>
      <input [ngFormControl]="ctrl"/>
    </form>

    <div *ngFor="#elt of elements | filter:filterValue">{{elt.name}}</div>
  `,
  pipes: [ FilterPipe ]
})
export class MyComponent {
  filterValue:string;
  ctrl:Control;

  contructor() {
    this.control = new Control();
    this.control.values.debounceTime(500).subscribe(
      (data) => {
        this.filterValue = data;
      }
    );
  }
}

Изменить

Вы также можете обновить filterValue по событиям кликов:

@Component({
  (...)
  template: `
    <div (click)="updateFieldValue('new value')">
      Update
    </div>

    <div *ngFor="#elt of elements | filter:filterValue">{{elt.name}}</div>
  `,
  pipes: [ FilterPipe ]
})
export class MyComponent {
  filterValue:string;

  updateFilterValue(newValue) {
    this.filterValue = newValue;
  }
}
person Thierry Templier    schedule 20.04.2016
comment
проблема в том, что я хочу управлять фильтром с помощью кнопок навигации - старых простых div. Поэтому я фактически не использую этот фильтр нигде в своем html. - person Miha Šušteršič; 20.04.2016
comment
Вы можете обновить filterValue из обработчиков кликов ;-) Я соответственно обновил свой ответ... - person Thierry Templier; 20.04.2016

Прежде чем использовать Pipe внутри компонента, вам необходимо добавить его в параметр pipe метаданных этого компонента.

@Component({
    selector: 'portfolio',
    templateUrl: '/app/views/portfolio.html',
    styleUrls: ['../app/styles/PortfolioMobile.css', '../app/styles/PortfolioOther.css'],
    pipes: [pagesFilter], //add pipe here
    encapsulation: ViewEncapsulation.None
})
person Pankaj Parkar    schedule 20.04.2016
comment
добавлены каналы: [pagesFilter], но все еще не работает должным образом. Также почему нет ошибки, когда я вызываю функцию, использующую фильтр, если фильтр не присутствует в компоненте? - person Miha Šušteršič; 20.04.2016
comment
обновил основной вопрос, так как я все еще не могу заставить фильтр работать. Спасибо за вклад - person Miha Šušteršič; 20.04.2016