question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ngClass behaving differently than regular classes with cdk-drag-drop

See original GitHub issue

I have different types of elements in my *cdkDropList that need different placholder hights when dragging them around. Since the array has objects with a property type, I added those types as CSS classes and tried to add them dynamically using [ngClass]. However, these dynamically generated classes behave differently than when I’m setting them as “regular” CSS classes.

This is what happens, when I set the classes dynamically:

The placeholder and the elements in the  overlap

The placeholder and the elements in the dropList overlap. Here’s the relevant code:

example.component.ts

contentItems: ContentItem[] = [
  { type: 'text', /* more props */ },
  { type: 'text', /* more props */ },
  { type: 'image', /* more props */ }
];

example.component.html

<div *ngFor="let item of contentItems" class="editor-item" cdkDrag>
  <div [ngClass]="['dropzone-placeholder', item.type]" *cdkDragPlaceholder>
    <p>{{ 'EDITOR.INSERT HERE' | translate }}</p>
  </div>

  <app-language-tab-editor *ngIf="item.type === 'text'"></app-language-tab-editor>
  <app-image-upload *ngIf="item.type === 'image'"></app-image-upload>
</div>

example.component.scss

$dropzone-placeholder-dark: #00973B;
$dropzone-placeholder-light: #00973B0D;
$text-placeholder-height: 135px;
$image-placeholder-height: 375px;

.dropzone-placeholder {
  border: 1px dashed $dropzone-placeholder-dark;
  color: $dropzone-placeholder-dark;
  background: $dropzone-placeholder-light;

  &.text {
    height: $text-placeholder-height;
  }

  &.image {
    height: $image-placeholder-height;
  }
}

I currently only have two different types, but the goal is to make it easily expandable to add more later on. I have also already tried to instead use class="dropzone-placeholder {{ item.type }}" as well as [class]="'dropzone-placeholder ' + item.type", to no avail.

After further testing I have also found out, that it generally doesn’t work using [ngClass], even if we don’t use a variable. Using [ngClass]="['dropzone-placeholder', 'text']" didn’t work either.

This is the expected behaviour:

The placeholder and the elements in the  don't overlap and are instead placed properly below each other

The placeholder and the elements in the dropList don’t overlap and are instead placed properly below each other. This behaviour can currently only be achieved by setting the classes regularily, but the HTML is rather unpleasant to look at, since the code would get messily redundant in the future:

example.component.html

<div *ngFor="let item of contentItems" class="editor-item" cdkDrag>
  <div *ngIf="item.type === 'text'">
    <div class="dropzone-placeholder reorder text" *cdkDragPlaceholder>
      <p>{{ 'EDITOR.INSERT HERE' | translate }}</p>
    </div>
  </div>
  <div *ngIf="item.type === 'image'">
    <div class="dropzone-placeholder reorder image" *cdkDragPlaceholder>
      <p>{{ 'EDITOR.INSERT HERE' | translate }}</p>
    </div>
  </div>

  <app-language-tab-editor *ngIf="item.type === 'text'"></app-language-tab-editor>
  <app-image-upload *ngIf="item.type === 'image'"></app-image-upload>
</div>

Environment

  • Angular: v8.3.25
  • CDK: v8.2.3
  • Browser(s): Chrome, Firefox
  • Operating System: Windows 10 (1803)

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
Achilles1515commented, Feb 27, 2020

@mladenbrankovic The problem is because you are specifying height values in your dynamic classes that change the div geometry…but these dynamic classes only get added after change detection runs on the template. I don’t know all the details, but I think the CDK code starts “using” this placeholder template before its first change detection run.

See this StackBlitz.

This demo includes a monkey patched _createPlaceholderElement() method. The only new code line is the one outlined in comments, manually triggering change detection on the dynamically instantiated template. Adding this line makes the placeholder work properly - comment it out to see otherwise.

It is still somewhat hard to see exactly what is going on with your drag setup based on those two images, but I think the above should fix it. I would try adding that monkey patch code to your project and see if it fixes the problem.

@crisbeto What are your thoughts on adding the detectChanges() line to _createPlaceholderElement() as well as _createPreviewElement() immediately after dynamic template instantiation?

0reactions
angular-automatic-lock-bot[bot]commented, Apr 12, 2020

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

Read more comments on GitHub >

github_iconTop Results From Across the Web

ngClass behaving differently than regular classes with cdk ...
I have different types of elements in my *cdkDropList that need different placholder hights when dragging them around. Since the array has ...
Read more >
Ngclass Behaving Differently Than Regular ... - ADocLib
ngClass behaving differently than regular classes with cdkdragdrop # I have different types of elements in my cdkDropList that need. Angular material provides ......
Read more >
Angular ngClass and ngStyle: The Complete Guide
In this post, we are going to learn the most commonly used options that we have available for styling our Angular components using...
Read more >
[Solved]-angular2 filtering issue-angular.js - appsloveworld
You're trying to compare each character of string from array with the entered text ... ngClass behaving differently than regular classes with cdk-drag-drop...
Read more >
Angular NgClass Example – How to Add Conditional CSS ...
ngClass is a directive in Angular [https://angular.io/api/common/NgClass] that adds and removes CSS classes on an HTML element.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found