You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular5拖拽排序时移除选中元素active类的问题求助

解决Angular拖拽时移除选中项active类的问题

你的问题在于之前用@ViewChild("myLabel")只能获取到第一个匹配的<li>元素,所以拖拽时只有第一个元素的active类被移除,其他选中的项没变化。而且直接操作DOM并不是Angular推荐的做法,我们可以通过状态绑定来更优雅地解决这个问题。

方案一:通过拖拽状态控制active类显示

这种方式利用Angular的属性绑定,在拖拽过程中暂时隐藏所有选中项的active样式,拖拽结束后自动恢复,完全符合Angular的响应式思路。

修改TypeScript代码:

首先添加一个dragging状态变量,用来标记是否处于拖拽状态,然后监听dragula的拖拽开始和结束事件来更新这个状态:

import {Component, OnInit} from '@angular/core';
import { DragulaService } from 'ng2-dragula';

export class SummaryComponent implements OnInit {
  // 初始化必要的数组(你原来的代码里可能漏了这部分)
  selectedQuestions: any[] = [];
  questions: any[] = [];
  // 新增拖拽状态标记
  dragging = false;

  constructor(private dragula: DragulaService){ }

  ngOnInit() {
    // 拖拽开始时设置dragging为true
    this.dragula.drag.subscribe(value => {
      this.dragging = true;
      console.log("拖拽开始");
    });

    // 拖拽结束(无论是否放下)时恢复状态
    this.dragula.dragend.subscribe(value => {
      this.dragging = false;
      console.log("拖拽结束");
    });
  }

  addThisQuestionToArray(person: any, i: number, event) {
    if (!event.ctrlKey) {
      this.selectedQuestions = [];
    }
    this.toggleItemInArr(this.selectedQuestions, person);
  }

  toggleItemInArr(arr, item) {
    const index = arr.indexOf(item);
    index === -1 ? arr.push(item) : arr.splice(index, 1);
  }

  isQuestionSelected(question: any) {
    return (this.selectedQuestions.indexOf(question) !== -1);
  }
}

修改HTML模板:

在[class.active]的判断条件里加上&& !dragging,这样拖拽时dragging为true,所有选中项的active类都会被移除:

<li class="well dragbox" *ngFor="let question of questions; let i = index"
  [attr.data-id]="question.QuestionId"
  [attr.data-index]="i"
  (click)="addThisQuestionToArray(question,i, $event)"
  [class.active]="isQuestionSelected(question) && !dragging" >
  {{i}} {{question.QuestionId}} {{question.Question}}
</li>

方案二:直接操作所有选中元素(不推荐)

如果你一定要通过DOM操作来实现,可以用@ViewChildren获取所有带#myLabel的元素,然后遍历移除active类。但这种方式需要在拖拽结束后重新添加选中项的active类,相对繁琐:

修改TypeScript代码:

import {Component, OnInit, ViewChildren, QueryList, ElementRef} from '@angular/core';
import { DragulaService } from 'ng2-dragula';

export class SummaryComponent implements OnInit {
  selectedQuestions: any[] = [];
  questions: any[] = [];
  // 获取所有myLabel元素
  @ViewChildren("myLabel") labels: QueryList<ElementRef>;

  constructor(private dragula: DragulaService){ }

  ngOnInit() {
    this.dragula.drag.subscribe(value => {
      console.log("拖拽开始");
      // 遍历所有元素移除active类
      this.labels.forEach(label => {
        label.nativeElement.classList.remove("active");
      });
    });

    this.dragula.dragend.subscribe(value => {
      console.log("拖拽结束");
      // 拖拽结束后,重新为选中的问题添加active类
      this.labels.forEach(label => {
        const questionId = label.nativeElement.dataset.id;
        const matchedQuestion = this.questions.find(q => q.QuestionId == questionId);
        if (this.isQuestionSelected(matchedQuestion)) {
          label.nativeElement.classList.add("active");
        }
      });
    });
  }

  // 其他方法和之前一样...
}

总结

推荐使用方案一,它更符合Angular的响应式编程理念,不需要手动操作DOM,代码更简洁易维护,也避免了DOM操作可能带来的各种问题。

内容的提问来源于stack exchange,提问作者Rosa Mystica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:53:26