Непонимание использования переменных шаблона в инструкции * ngIf

моя цель состоит в том, чтобы в конечном итоге сделать настройку, в которой пользователь может изменять количество строк, просматривая каталог (spiritwoodart.com). Я даже не прошел первый этап возни, когда столкнулся с проблемой. Догадываться - это фундаментальное недоразумение. Возникли проблемы с поиском справки (например, мой поиск отстой: «почему я не могу поместить переменные шаблона в оператор ngif»). Пожалуйста, дайте мне знать, если потребуется дополнительная информация. Спасибо за любые идеи или даже пламя за мою новизну.

Итак, когда я меняю

это:

            <div *ngIf="(i+1) % n === 0"
                class="w-100"></div>

к этому:

или это:

            <div #n='3' *ngIf="(i+1) % n === 0"
                class="w-100"></div>

или даже это:

            <div *ngIf="(i+1) % {{3}} === 0"
                class="w-100"></div>

Я получаю ошибку, которая выглядит так:

compiler.js:485 Uncaught Error: Template parse errors:
There is no directive with "exportAs" set to "3" ("
                        [cart]="cart"></product-card>
                </div>
                <div [ERROR ->]#n='3' *ngIf="(i+1) % n === 0"
                    class="w-100"></div>
            </ng-container>
"): ng:///AppModule/ProductsComponent.html@12:21

шаблон контекста:

<div class="row">
    <div class="col-3">
        <product-filter [category]="category"></product-filter>
    </div>
    <div class="col">
        <div class="row"
            *ngIf="cart$ | async as cart">
            <ng-container *ngFor="let p of filteredProducts; let i = index">
                <div class="col">
                    <product-card [product]="p"
                        [cart]="cart"></product-card>
                </div>
                <div *ngIf="(i+1) % 3 === 0"
                    class="w-100"></div>
            </ng-container>
        </div>
    </div>
</div>

контекст-компонент:

import { Cart } from './../models/cart';
import { CartService } from './../cart.service';
import { Product } from './../models/product';
import { ProductService } from './../product.service';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import 'rxjs/add/operator/switchMap';
import { Subscription } from 'rxjs/Subscription';
import { Observable } from 'rxjs/Observable';
@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.css']
})
export class ProductsComponent implements OnInit {
  products: Product[] = [];
  filteredProducts: Product[] = [];
  category: string; // keep this field in this class in order to initialize it... then delegate it out
  cart$: Observable<Cart>;

  constructor(
    private route: ActivatedRoute,
    private productService: ProductService,
    private cartService: CartService
  ) {}

  async ngOnInit() {
    this.cart$ = await this.cartService.getCart();
    this.populateProducts();
  }

  private populateProducts() {
    this.productService
      .getAll()
      .switchMap(products => {
        this.products = products;
        return this.route.queryParamMap;
      })
      .subscribe(params => {
        this.category = params.get('category'); // initializing category field
        this.applyFilter();
      });
  }

  private applyFilter() {
    // setting the filtered products array
    this.filteredProducts = this.category
      ? this.products.filter(p => p.category === this.category)
      : this.products;
  }
}

person imnickvaughn    schedule 24.02.2018    source источник
comment
Ну, тогда не меняй выражения. Тот, что в первом фрагменте, правильный. Все, что вам нужно от общедоступного свойства n в вашем компоненте.   -  person JB Nizet    schedule 24.02.2018
comment
‹div #n='3' *ngIf=(i+1) % n === 0 class=w-100›‹/div› это верно? а потом просто объявить как публичный? Круто   -  person imnickvaughn    schedule 24.02.2018
comment
этот ‹div *ngIf=(i+1) % n === 0 class=w-100›‹/div›   -  person Abhishek Ekaanth    schedule 24.02.2018
comment
Нет, это не так, как говорит вам компилятор: нет директивы с экспортом, установленным на 3.   -  person JB Nizet    schedule 24.02.2018
comment
зачем надо было так просто!? ха-ха Нет, но серьезно, здесь нет способа использовать входные данные шаблона или ссылочные переменные? просто для удовольствия   -  person imnickvaughn    schedule 24.02.2018
comment
То, что вы пытаетесь сделать, изначально не поддерживается именно потому, что это «для развлечения». Было доказано, что ng-init в целом является антипаттерном в AngularJS, поэтому он не был включен в Angular. Используйте класс компонента для настройки константы.   -  person Estus Flask    schedule 24.02.2018


Ответы (2)


# – это ссылочная переменная шаблона. Он зависит от элемента DOM и не может использоваться таким образом.

Директива ng-init существует в AngularJS и служит для этой цели, но ее нет в Angular, прежде всего потому, что ею можно злоупотреблять. Его можно воссоздать, как показано в этом ответе.

Обходной путь — использовать структурную директиву. Типичным обходным решением для значения truethy является структурная директива ngIf:

<ng-container *ngIf="3; let n">
  <div *ngIf="(i+1) % n === 0">
    ...

Это не сработает, если значение равно falsy, потому что вложенный компонент не будет скомпилирован. Более универсальным обходным решением, которое поддерживает ложные значения, является пользовательская структурная директива ngVar, как описано здесь.

person Estus Flask    schedule 24.02.2018

Для таких же новичков, как я, вот что я сделал на данный момент с советом JB... Спасибо, JB. И я надеюсь, что это поможет кому-то еще.

всего несколько изменений...

шаблон:

<div class="row">
        <input #myInput (change)="changeColumnNumber(myInput.value)" type="number">
</div>

составная часть:

  n = 4;

Полный контекст:

шаблон:

    <div class="row">
        <input #myInput (change)="changeColumnNumber(myInput.value)" type="number">
</div>

<div class="row">
    <div class="col-3">
        <product-filter [category]="category"></product-filter>
    </div>

    <div class="col">
        <div class="row"
            *ngIf="cart$ | async as cart">
            <ng-container *ngFor="let p of filteredProducts; let i = index">
                <div class="col">
                    <product-card [product]="p"
                        [cart]="cart"></product-card>
                </div>
                <div *ngIf="(i+1) % n === 0"
                    class="w-100"></div>
            </ng-container>
        </div>
    </div>
</div>

составная часть:

import { Cart } from './../models/cart';
import { CartService } from './../cart.service';
import { Product } from './../models/product';
import { ProductService } from './../product.service';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import 'rxjs/add/operator/switchMap';
import { Subscription } from 'rxjs/Subscription';
import { Observable } from 'rxjs/Observable';
@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.css']
})
export class ProductsComponent implements OnInit {
  products: Product[] = [];
  filteredProducts: Product[] = [];
  category: string; // keep this field in this class in order to initialize it... then delegate it out
  cart$: Observable<Cart>;
  n = 4;


  constructor(
    private route: ActivatedRoute,
    private productService: ProductService,
    private cartService: CartService,

  ) {}

  async ngOnInit() {
    this.cart$ = await this.cartService.getCart();
    this.populateProducts();
  }

  private populateProducts() {
    this.productService
      .getAll()
      .switchMap(products => {
        this.products = products;
        return this.route.queryParamMap;
      })
      .subscribe(params => {
        this.category = params.get('category'); // initializing category field
        this.applyFilter();
      });
  }

  private applyFilter() {
    // setting the filtered products array
    this.filteredProducts = this.category
      ? this.products.filter(p => p.category === this.category)
      : this.products;
  }

  changeColumnNumber(value) {
    console.log(value);
    this.n = value;
    console.log(this.n);
  }
}
person imnickvaughn    schedule 24.02.2018