Ошибка синтаксического анализа углового шаблона/интерполяции при поиске/фильтре

Ошибка:

Error: Template parse errors: Parser Error: Bindings cannot contain assignments at....

line: <div>Closed: {{blah}}.find()...

HTML:

<div fxLayout = "row" fxLayoutAlign = "start center" fxLayoutGap = "4px">
  <div>Total: {{(issuesData$ | async)?.length}}</div>
  <div>Closed: {{(issuesData$ | async)?.filter(data => {data.closedOn}).length}}</div>
</div>

Мне любопытно, можно ли использовать поиск/фильтр, не сталкиваясь с ошибкой синтаксического анализа шаблона, когда поиск/фильтр вызывается для коллекции в операторе интерполяции.

Обновлено:Angular 2 - привязки не могут содержать назначения — у меня это не работает, потому что я передаю компоненту Observable. OnInit я присваиваю переменную данных @Input наблюдаемому объекту IssueData$. Использование чего-то вроде {{getCount()}} в интерполяции приводит к отсутствию данных. Я попытался реализовать это следующим образом:

УГЛОВОЙ:

@Input()
data;

ngOnInit() {
  this.issuesData$ = this.data;
  
}

getCount(){
  this.issuesData$.subscribe(data => {
    return data.length;
  })
}

HTML:

 <div>Total: {{getCount()}}</div>

Но подписаться не на что, когда в интерполяции вызывается getCount() и это тоже не работает {{(getCount() | async}}

Возможный дубликат Angular 2 - привязки не могут содержать назначения

mbojko 10.04.2019 15:48

@mbojko Пожалуйста, посмотрите мое редактирование вопроса, спасибо.

Jacob Barnes 10.04.2019 16:13

Почему бы не использовать map вместо этого? Это был бы более чистый способ сделать это ИМО.

Igor 10.04.2019 16:42
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
1
3
385
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы должны подписаться на свой Observable и вместо этого вручную назначать нужные переменные, просто чтобы уменьшить сложность кода вашего шаблона.

@Input()
data;

total: number;
closed: number;

ngOnInit() {
  this.issuesData$ = this.data;
  this.issuesData$.subscribe(next => {
    this.total = next.length;
    this.closed = next.filter(x => x.closedOn).length;
  }
}

Затем просто используйте переменные total и closed в своем шаблоне.

Чтобы вызвать find или filter из асинхронного массива в шаблоне, определите обратный вызов в классе компонента. Например, вы можете установить метод isClosedOn в качестве обратного вызова filter:

<div>Closed: {{ (issuesData$ | async)?.filter(isClosedOn).length }}</div>

и определите его следующим образом в классе компонента:

public isClosedOn = data => data.closedOn;

См. этот стекблиц для демонстрации.

Ответ принят как подходящий
  • В этом сценарии вы должны использовать map и отформатировать ответ таким образом, чтобы данные можно было легко использовать в компоненте/шаблоне.
  • Также вы не можете вернуть значение из subscribe, хотя вы можете присвоить значение.
  • find возвращает одно совпадение, filter возвращает массив. Вы хотели использовать filter, если хотите увидеть общее количество совпадений, используя length
  • Если вы используете shareReplay, наблюдаемый будет разрешен один раз, поэтому его можно будет вызывать несколько раз, используя либо async каналы, либо subscribe без дополнительных затрат, если он делает что-то с внешними ресурсами, например, делает http-запрос.
  • Наконец, вы должны определить типы/определения, typescript (может быть) строго типизирован, и это большое преимущество перед javascript (то, что он заменяет).

Шаблон.html

<div>Total: {{(issuesData$ | async)?.length}}</div>
<div>Closed: {{(issuesData$ | async)?.closedOnLength}}</div>

ВашКомпонент.ts

import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';


@Input()
data: Observable<{closedOn:any}[]>;
issuesData$: Observable<{length: number, closedOnLength: number}>;

ngOnInit() {
  this.issuesData$ = this.data.pipe(map((_) => {
    return {
      length: _.length,
      closedOnLength: _.filter(d => d.closedOn).length
    };
  }), shareReplay());
}

count: number;
readCount() {
  // you can't return data in a subscribe callback, it is asynchronous
  // you can assign a value though
  this.issuesData$.subscribe(_ => this.count = _.length);
}

Мне нравятся ваши ответы и ответы ConnorsFan. Я довольно быстро понял свою ошибку с подпиской/возвратом и в итоге выполнил задание, которое в конечном итоге превратилось в подробную версию ответа Nothematic.

Jacob Barnes 10.04.2019 18:12

Другие вопросы по теме