简体   繁体   English

ESLint - 选择器应该用作元素

[英]ESLint - The selector should be used as an element

I'm using Angular 12 along with ESLint.我正在使用 Angular 12 和 ESLint。 Whenever I execute ng lint , ESLint is angry at the following selector.每当我执行ng lint ,ESLint 对下面的选择器很生气。

10:13 error The selector should be used as an element ( https://angular.io/guide/styleguide#style-05-03 ) @angular-eslint/component-selector 10:13 错误选择器应该用作元素( https://angular.io/guide/styleguide#style-05-03)@angular-eslint/component-selector

Usage:用法:

<li app-menu-item *ngFor="let item of model; let i = index" [item]="item" [index]="i" [root]="true"></li>

I could remove that rule from .eslintrc.json , but I would rather fix it.我可以从.eslintrc.json删除该规则,但我宁愿修复它。 How do I fix it?我如何解决它?

import { Component, Input, OnInit, ChangeDetectorRef, OnDestroy, HostBinding } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';
import { LayoutComponent } from '../layout.component';
import { MenuService } from '@core/services';

@Component({
  selector: '[app-menu-item]',
  template: `
    <ng-container>
      <a
        [attr.href]="item.url"
        (click)="itemClick($event)"
        *ngIf="!item.routerLink || item.items"
        pRipple
        [ngClass]="item.class"
        (mouseenter)="onMouseEnter()"
        (keydown.enter)="itemClick($event)"
        [attr.target]="item.target"
        [attr.tabindex]="0"
      >
        <i [ngClass]="item.icon" class="layout-menuitem-icon"></i>
        <span class="layout-menuitem-text">{{ item.label }}</span>
        <i class="pi pi-fw pi-angle-down layout-submenu-toggler" *ngIf="item.items"></i>
      </a>
      <a
        (click)="itemClick($event)"
        (mouseenter)="onMouseEnter()"
        *ngIf="item.routerLink && !item.items"
        pRipple
        [ngClass]="item.class"
        [routerLink]="item.routerLink"
        routerLinkActive="active-menuitem-routerlink"
        [routerLinkActiveOptions]="{ exact: true }"
        [attr.target]="item.target"
        [attr.tabindex]="0"
      >
        <i [ngClass]="item.icon" class="layout-menuitem-icon"></i>
        <span class="layout-menuitem-text">{{ item.label }}</span>
        <i class="pi pi-fw pi-angle-down layout-submenu-toggler" *ngIf="item.items"></i>
      </a>
      <ul
        *ngIf="item.items && (active || animating || selectedKey)"
        (@children.done)="onAnimationDone()"
        [ngStyle]="{ padding: active && root ? '' : '0' }"
        [@children]="
          app.isHorizontal() && root && !app.isMobile()
            ? active
              ? 'visible'
              : 'hidden'
            : active
            ? 'visibleAnimated'
            : 'hiddenAnimated'
        "
      >
        <ng-template ngFor let-child let-i="index" [ngForOf]="item.items">
          <li
            app-menu-item
            [item]="child"
            [index]="i"
            [parentKey]="key"
            [class]="child.badgeClass"
          ></li>
        </ng-template>
      </ul>
    </ng-container>
  `,
  animations: [
    trigger('children', [
      state(
        'void',
        style({
          height: '0px'
        })
      ),
      state(
        'hiddenAnimated',
        style({
          height: '0px'
        })
      ),
      state(
        'visibleAnimated',
        style({
          height: '*'
        })
      ),
      state(
        'visible',
        style({
          height: '*',
          'z-index': 999
        })
      ),
      state(
        'hidden',
        style({
          height: '0px',
          'z-index': '*'
        })
      ),
      transition(
        'visibleAnimated => hiddenAnimated',
        animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')
      ),
      transition(
        'hiddenAnimated => visibleAnimated',
        animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')
      ),
      transition(
        'void => visibleAnimated, visibleAnimated => void',
        animate('400ms cubic-bezier(0.86, 0, 0.07, 1)')
      )
    ])
  ]
})
export class MenuItemComponent implements OnInit, OnDestroy {
  @HostBinding('class.active-menuitem') get activeMenuItem(): boolean {
    return (
      (this.selectedKey && this.app.isHorizontal()) ||
      (this.active && !this.app.isHorizontal()) ||
      (this.active && !this.root && this.app.isHorizontal())
    );
  }

  @HostBinding('class.active-rootmenuitem') get activeRootMenuItem(): boolean {
    return this.active && this.root && this.app.isHorizontal();
  }

  @Input() item: any;
  @Input() index: number;
  @Input() root: boolean;
  @Input() parentKey: string;

  animating: boolean;
  active = false;
  menuSourceSubscription: Subscription;
  menuResetSubscription: Subscription;

  key: string;

  selectedKey: boolean;

  constructor(
    public app: LayoutComponent,
    public router: Router,
    private cd: ChangeDetectorRef,
    private menuService: MenuService
  ) {
    this.menuSourceSubscription = this.menuService.menuSource$.subscribe((key) => {
      // deactivate current active menu
      if (this.active && this.key !== key && key.indexOf(this.key) !== 0) {
        this.active = false;
      }
    });

    this.menuResetSubscription = this.menuService.resetSource$.subscribe(() => {
      this.active = false;
    });

    this.router.events
      .pipe(filter((event) => event instanceof NavigationEnd))
      .subscribe((params) => {
        if (this.app.isHorizontal() && this.item.routerLink) {
          this.active = false;
          this.selectedKey = this.router.isActive(
            this.item.routerLink[0],
            this.item.items ? false : true
          );
        } else {
          if (this.item.routerLink) {
            this.updateActiveStateFromRoute();
          } else {
            this.active = false;
          }
        }
      });
  }

  ngOnInit() {
    if (!this.app.isHorizontal() && this.item.routerLink) {
      this.updateActiveStateFromRoute();
    }

    if (this.app.isHorizontal() && this.item.routerLink) {
      this.active = false;
      this.selectedKey = this.router.isActive(
        this.item.routerLink[0],
        this.item.items ? false : true
      );
    }

    this.key = this.parentKey ? this.parentKey + '-' + this.index : String(this.index);
  }

  updateActiveStateFromRoute() {
    this.active = this.router.isActive(this.item.routerLink[0], this.item.items ? false : true);
  }

  itemClick(event: Event) {
    // avoid processing disabled items
    if (this.item.disabled) {
      event.preventDefault();
      return;
    }

    // navigate with hover in horizontal mode
    if (this.root) {
      this.app.menuHoverActive = !this.app.menuHoverActive;
    }

    // notify other items
    this.menuService.onMenuStateChange(this.key);

    // execute command
    if (this.item.command) {
      this.item.command({ originalEvent: event, item: this.item });
    }

    // toggle active state
    if (this.item.items) {
      this.active = !this.active;
      this.animating = true;
    } else {
      // activate item
      this.active = true;

      // reset horizontal menu
      if (this.app.isHorizontal()) {
        this.menuService.reset();
      }

      this.app.overlayMenuActive = false;
      this.app.overlayMenuMobileActive = false;
      this.app.menuHoverActive = !this.app.menuHoverActive;
    }
  }

  onMouseEnter() {
    // activate item on hover
    if (this.root && this.app.menuHoverActive && this.app.isHorizontal() && this.app.isDesktop()) {
      this.menuService.onMenuStateChange(this.key);
      this.active = true;
    }
  }

  onAnimationDone() {
    this.animating = false;
  }

  ngOnDestroy() {
    if (this.menuSourceSubscription) {
      this.menuSourceSubscription.unsubscribe();
    }

    if (this.menuResetSubscription) {
      this.menuResetSubscription.unsubscribe();
    }
  }
}

Component selector should be used as an element, ie组件选择器应该作为一个元素使用,即

<app-menu-item *ngFor="let item of model; let i = index" [item]="item" [index]="i" [root]="true"></app-menu-item>

Plus selector should be without brackets (with a predefined eslint config) Plus 选择器应该没有括号(带有预定义的 eslint 配置)

@Component({
  selector: 'app-menu-item',
...

Alternatively you can change eslint configuration或者,您可以更改eslint 配置

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM