如何用* ngFor使用自定义指令中的组件替换目标元素?

问题描述 投票:0回答:1

我正在构建一个指令,它应该替换组件(加载器)所包含的元素,并在达到延迟时发送错误消息。

遇到的问题:列表的所有元素都由加载器替换,而不是我单击的加载器。

我找不到一种方法来只选择已被点击的元素。

Stackblitz:https://stackblitz.com/edit/angular-wmybgc?file=src%2Fapp%2Floader-and-error-handler.directive.ts

指令:


    import { StoreService } from '@services/store/store.service';
    import { Directive, Input, ViewContainerRef, TemplateRef, ComponentFactoryResolver, Type } from '@angular/core';
    import { LoaderComponent } from '@components-ui/loader/loader.component';

    export class LoaderAndErrorContext {
      $implicit: boolean;
      message: string;
    }

    @Directive({
      selector: '[loaderAndErrorHandler]'
    })
    export class LoaderAndErrorHandlerDirective {

      private isLoading: boolean;

      @Input('loaderAndErrorHandlerWait') private delay: number;
      @Input('loaderAndErrorHandlerBeforeDisplaying') private message: string;
      @Input() set loaderAndErrorHandler(isLoading: boolean) {

        this.isLoading = isLoading;

        this.viewControllerRef.clear();

        if (this.isLoading) {

          this.displayComponent(LoaderComponent);

          setTimeout(() => {
            this.store.sendNotification(this.message);
          }, this.delay);
        }
        else {
          this.viewControllerRef.clear();
          this.viewControllerRef.createEmbeddedView(this.templateRef);
        }
      }

      constructor(
        private viewControllerRef: ViewContainerRef,
        private templateRef: TemplateRef<any>,
        private componentFactoryResolver: ComponentFactoryResolver,
        private store: StoreService
      ) {
        this.displayComponent = this.displayComponent.bind(this);
      }

      displayComponent = (component: Type<LoaderComponent>, message?: string): void => {
        const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
        message
          ? this.viewControllerRef.createComponent(componentFactory).instance['message'] = message
          : this.viewControllerRef.createComponent(componentFactory);
      }
    }

实施:

<h2>Mes documents</h2>
<ul [@fadeInOutStagger]="documents.length">
  <ng-container *loaderAndErrorHandler="isLoading; wait 2000 beforeDisplaying errorMessage;">
  <li *ngFor="let document of documents | sortBy:'label'">
      <article (click)="getDocument(document.id)" class="document-label">
        <input type="image" src="assets/images/icon/icone_document.svg">
        <label>
          <strong>{{document.label}}</strong>
        </label>
      </article>
      <article class="document-date">
        <p>{{document.date | dateTo:'JJ Mois'}}</p>
      </article>
  </li>
  </ng-container>
</ul>
angular angular2-directives
1个回答
0
投票

你可以这样做:

<h2>Mes documents</h2>
<ul>
  <ng-container *ngFor="let document of documents; let i = index" >
  <li *loaderAndErrorHandler="document.isLoading; wait 2000 beforeDisplaying errorMessage;">
      <article (click)="getDocument(document.id, i)" class="document-label">
        <img src="https://image.noelshack.com/fichiers/2019/11/7/1552854323-iconfinder-note3-254240.png" height="20px" width="20px">
        <label>
          <strong>{{document.label}}</strong>
        </label>
      </article>
      <article class="document-date">
        <p>{{document.date}}</p>
      </article>
  </li>
  </ng-container>
</ul>

getDocument方法将循环索引作为额外的参数,以检索要更新的好的索引。例如,您必须选择不同的值以确保数据中存在文档。

import { Component, Input, ViewRef } from '@angular/core';
import { StoreService } from './services/store/store.service';
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {

  documents = [
    {
      id: '123',
      label: 'Certificat of something great',
      date: '15 jun.',
      isLoading: false
    },
    {
      id: '123',
      label: 'Certificat of something not so great',
      date: '15 jun.',
      isLoading: false
    },
    {
      id: '123',
      label: 'Certificat of something ok',
      date: '15 jun.',
      isLoading: false
    },
  ];

  public errorMessage = 'Erreur: Une erreur s\'est produite durant la récupération de votre document.\nVeuillez renouveler votre requête ultérieurement.'

  constructor(private store: StoreService) {
    this.store.notificationPublisher.subscribe(notification => {
      console.log('Notification:', notification)
    })
  }

  public getDocument = (documentId: string, documentIndex: number): void => {
    this.documents[documentIndex].isLoading = true;
    setTimeout(() => {
      this.documents[documentIndex].isLoading = false;
    }, 1000)
  }
}

我只为每个文档添加了一个状态,以及使用*ngFor循环的项目

编辑:你可以在这里测试=> https://stackblitz.com/edit/angular-hfnhg7

© www.soinside.com 2019 - 2024. All rights reserved.