0

I am trying to implement nested drag and drop functionality in angular project. For this I am using https://www.npmjs.com/package/ng-drag-drop.

HTML:

<ul>
  <li class="parent" draggable [dragScope]="'parentLayout'">Row with Tow Columns</li>
</ul>

<div droppable [dropScope]="'parentLayout'" [dragOverClass]="'drag-target-border'" (onDrop)="onLayoutDrop($event)">
  <div class="layout-container">Add Element Container Here</div>
</div> 

Inside the 'layout-container' I want to drag and drop another HTML code. which is:

<div class="container">
  <div class="row">
    <div class="col-6" droppable [dropScope]="'element'">Column A - Add Element</div>
    <div class="col-6" droppable [dropScope]="'element'">Column B - Add Element</div>
  </div>
</div>

As you can notice, I want to enable second droppable div inside parent div. This works perfectly when I hardcoded the code. However, I want to fetch the code from database. So I tried using innerHTML, but its not detecting the ng-drag-drop scopes (droppable, [dropScope], etc).


.ts

inner_html: string = '';

// Fetched from database
layout: any = `<div class="container">
      <div class="row">
        <div class="col-6" droppable [dropScope]="'element'">Column A - Add Element</div>
        <div class="col-6" droppable [dropScope]="'element'">Column B - Add Element</div>
      </div>
    </div>`;

innerElement: string = `<h1>Final Element</h1>`; // This is fetched from database

onLayoutDrop(){
 this.inner_html += this.layout;
}

.html

  <ul>
     <li class="parent" draggable [dragScope]="'parentLayout'">Row with Tow Columns</li>
  </ul>
    
   <div droppable [dropScope]="'parentLayout'" [dragOverClass]="'drag-target-border'" (onDrop)="onLayoutDrop($event)">
      <div class="layout-container">Add Element Container Here</div>
   </div> 

   <div class="innerhtml" [innerHTML]="layout"></div>
Giannis
  • 1,790
  • 1
  • 11
  • 29
  • Why aren't you using `@angular/cdk`? – Pieterjan Oct 20 '22 at 18:04
  • I think that [this answer](https://stackoverflow.com/a/48028892/8941307) might help you as well to apply directives to dynamically inserted html coming from a database – Pieterjan Oct 20 '22 at 18:17
  • @Pieterjan I really do not think that this is the solution for his problem. He should better just fetch the data from the db, inject it via @Input() to components that are rendered with ngFor. There is a bad misconception in his model when the HTML is saved in the db – SirOneOfMany Oct 26 '22 at 12:16

1 Answers1

0

Hey I hope you have the possibility to change your data that is fetched from the api. I really hope you get a proper model in JSON format and do not get some rigged HTML from your backend.

Because:

  1. The data persistence should not know how the data is presented
  2. HTML in the Database is a security flaw
  3. With innerHtml you are working around angulars change detection

My advice: If it feels quirky to implement, it usually is quirky to implement.

So to a solution for your very problem:

  1. Separate Data from Layout:

    export interface SomeElement {
       description: string;
    }
    
  2. Use *ngFor

    <div class="container">
       <div class="row">
          <div class="col-6" droppable [dropScope]="'element'" *ngFor="let element of elementsFromDb">{{ element.description }}</div>
       </div>
    </div>
    
  3. fetch data

elementsFromDb: SomeElement = /* fetch an array that looks like this [{ description: 'Column A - Add Element' }, { description: 'Column B - Add Element'}] */
SirOneOfMany
  • 929
  • 5
  • 15