【问题标题】:Angular: Add/Remove elements from DOMAngular:从 DOM 中添加/删除元素
【发布时间】:2019-10-20 21:56:48
【问题描述】:

为了解决problem with dragula,我想我应该从 DOM 中添加和删除元素。目标是使用一些占位符元素来获得我想要的布局(在所有分辨率下居中容器中的左对齐元素)。这些占位符元素必须放在最后!

我尝试了以下方法:

  • ngIf:这里的问题是 invisible 元素可能没有放在最后。通过拖放,可能会发生被拖放的元素位于最后一个位置,而 invisible 元素位于其间。
  • push elements on the array:在这里我尝试在 ngClass 指令的帮助下添加类 invisible,但是当我设置布尔变量时它没有正确更新它推动阵列上的项目。该课程从未应用过。
  • ElementRef:从 DOM 中删除元素是可行的,但我不知道如何添加一个
  • Renderer2:我目前的方法,removeChild() 只删除一个孩子,尽管它被第二次调用了

模板:

<div #button_area class="button_area" dragula="cards" [dragulaModel]="cards" (dragulaModelChange)="cards = $event">
  <div *ngFor="let c of cards" id="{{ 'card-' + c.id }}" [ngClass]="calculateClasses(c)" [ngStyle]="calculateStyles(c)" (click)="onSelect($event, c)">
    <!-- some irrelevant html code -->
  </div>
</div>

打字稿:

@ViewChild('button_area') private buttonAreaElement: ElementRef;

constructor(public dragulaService: DragulaService,
          private renderer: Renderer2) {
    // something irrelevant
}

addPlaceholderElements() {
    const placeholder = this.buttonAreaElement.nativeElement.querySelector('.invisible');

    if (placeholder === null) {
        const placeholder1 = this.renderer.createElement('div');
        this.renderer.addClass(placeholder1, 'card');
        this.renderer.addClass(placeholder1, 'invisible');
        this.renderer.appendChild(this.buttonAreaElement.nativeElement, placeholder1);

        const placeholder2 = this.renderer.createElement('div');
        this.renderer.addClass(placeholder2, 'card');
        this.renderer.addClass(placeholder2, 'invisible');
        this.renderer.appendChild(this.buttonAreaElement.nativeElement, placeholder2);
    }
}

removePlaceholderElements() {
    const placeholder1 = this.buttonAreaElement.nativeElement.querySelector('.invisible');
    if (placeholder1 !== null) {
        this.renderer.removeChild(this.buttonAreaElement.nativeElement, placeholder1);
    }

    const placeholder2 = this.buttonAreaElement.nativeElement.querySelector('.invisible');
    if (placeholder2 !== null) {
        this.renderer.removeChild(this.buttonAreaElement.nativeElement, placeholder2);
    }
}

如您所见,我为此使用了querySelector() 方法。 placeholder2 已找到,但未从 DOM 中删除。但是为什么呢?

我正在使用 Angular v. 7.2.5。

编辑:

Here 是 MVCE。那里不会出现删除问题。还没弄清楚有什么区别...为什么removeChild()不删除孩子?这是时间问题吗?

【问题讨论】:

  • 自己修改 DOM 通常是个坏主意。尤其是像 Dragula 这样的 Angular 库。请提供minimal reproducible example 您的问题,我会看看如何解决您的问题!
  • @Maryannah:我添加了一个 stackblitz 项目(请参阅已编辑的问题)。也许你有更好的想法来解决这个问题。
  • dragula 也有一两个问题 - 为什么不使用来自 @angular/cdk/drag-drop 的原生 ng-7 CdkDragDrop, moveItemInArray, transferArrayItem 而不是 dragula?
  • @iLuvLogix 我喜欢这个建议。 Dragula 比 CDK 旧且更新少!至于OP,我现在就看,让你更新
  • OP,你到底有什么问题?重现的步骤是什么?

标签: angular


【解决方案1】:

回答我自己的问题:

如问题所示,添加或删除元素有多种方法(例如通过Renderer2)。一般来说,不建议像Maryannah 所说的那样直接操作 DOM。但有时这是最后的手段。

为了获得正确的布局,我使用占位符元素。当我使用占位符元素时,这些是 Dragula 的可能位置。我不希望它们作为放置位置。因为我不能排除这些占位符元素,所以我认为我会根据需要添加和删除它们。在我最后一次尝试中,我使用了 Renderer2。在我的真实项目中,removeChild 不会删除子元素,并且会保留一个(两个)占位符元素。在 MVCE 中不是这样,但我不知道为什么。

我的解决方法缺少的是完全删除所有具有 CSS 类 invisible 的子项。这现在也适用于我的本地开发环境:

removePlaceholderElements() {
    const placeholders = this.buttonAreaElement.nativeElement.querySelectorAll('.invisible');
    for (var i = 0; i < placeholders.length; i++) {
        this.renderer.removeChild(this.buttonAreaElement.nativeElement, placeholders[i]);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-19
    • 1970-01-01
    • 2014-09-01
    • 2019-02-21
    • 2017-07-19
    • 2021-12-19
    • 2018-12-03
    相关资源
    最近更新 更多