Class binding is not being evaluated

I have an app where I’m trying to allow the user to map one item to another. I’m doing this using a series of drag and drop items. When dragging the source over the target, I want the target to be highlighted.

My code (below) does not work – initially; however, when running the code, if I make a change and let Webpack push out the changes to my running code, then the highlighting starts working.

Originally, I thought it had to do with my use of <template> in my repeat.for; however, I changed the html to use a table with no <template> and I get the same result.

Why is my embedded expression class="dropzone ${targetItem == target ...}" not being evaluated when targetItem changes? Why does it start getting evaluated after Webpack pushes out new code on the fly?

Note: The key part in the html is the class attribute of the div in the targets area: <div class="dropzone ..."

EDIT For grins, I added click.delegate="targetItem = target" to the div in question. This works as expected – clicking the target box causes it to be highlighted – even without the app refresh like mentioned above.

mapping.ts

public class Mapping{
    public draggedItem : any;
    public targetItem : any;

    public dragStart(event, source){
        this.draggedItem = source;
        this.targetItem = null;
        return true;
    }

    public dragOver(event, target){
        if(this.draggedItem){
            event.preventDefault();
            this.targetItem = target;
        }
    }

    public dragDrop(event, target) {
        if(this.draggedItem){
            event.preventDefault();
            this.targetItem = null;
            target.sourceItem = this.draggedItem;
            this.draggedItem = null;
        }
    }

    public dragLeave(event, target) {
        event.preventDefault();
        if(this.targetItem == target)
             this.targetItem = null;
}

mapping.html

<template>
    <require from="./mapping.scss"></require>
    <div class="container">
        <div class="sources">
            <div repeat.for="source of sources" dragstart.trigger="dragStart($event,source)">${source.name}</div>
        </div>

        <div class="targets">
             <div class="targetGrid">
                <template repeat.for="target of targets">
                    <div class="dropzone ${targetItem == target ? 'hover' : ''}" 
                             dragover.trigger="dragOver($event,target)"  
                             dragdrop.trigger="dragDrop($event, target)" 
                             dragleave.trigger="dragLeave($event, target)">
                          ${target.sourceItem.name}
                    </div>
                    <div>...</div>
                    <div>${target.name}</div>
                 </template>
              </div>
         </div>
    </div>
</template>

mapping.css

.targetGrid {
     display: grid;
     grid-template-columns: auto 2.5em 1fr;
 }

 .dropzone {
     border: 2px dotted lightgray;
  }  
 .dropzone.hover {
     border: 2px dotted rgba(101,141,27,1);
     background-color: rgba(101,141,27,.5);
 }
1 Like

Maybe for

<div class="dropzone ${targetItem == target ? 'hover' : ''}" 
  dragover="dragOver($event,target)"  
  dragdrop="dragDrop($event, target)" 
  dragleave="dragLeave($event, target)">
  ${target.sourceItem.name}
</div>

you meant:

<div class="dropzone ${targetItem == target ? 'hover' : ''}" 
  dragover.trigger="dragOver($event,target)"
  dragleave.trigger="dragLeave($event, target)"
  drop.trigger="dragDrop($event, target)">
  ${target.sourceItem.name}
</div>

For drag/drop, note that Aurelia by default calls event.preventDefault() for you, if you don’t return true in your handler. It could save some code, or could cause some surprises.

Thanks, yes, my code does include .trigger on all those drag/drop events. I’ll update my original post to include the .trigger.

Thanks for the note about Aurelia’s default behavior.

1 Like

BTW, I’ve seen you use CodeSandbox in the past for mocking up an Aurelia solution. Two questions:

  1. I don’t see a Client Template for Aurelia, are there plans to create one?
  2. I was trying to mock up my issue on CodeSandbox using code that someone else had put together for their issue as a starting point. (partly so people could see it and partly to see if I could isolate my issue without all the extra baggage of the rest of my project). I ran into the issue of not being able to use css. <require> does not seem to work and I couldn’t get <link ...> in the index.js page to work. Is there a way to use css with Aurelia in CodeSandbox?
1 Like

Okay, my bad (he says blushing :stuck_out_tongue_winking_eye:).

I was not initializing my property:

public targetItem : any;

when changed to

public targetItem : any = null;

works! Sorry for the wasted post. Maybe it’ll helps someone else catch a dumb mistake faster than I did.

1 Like

Yes, there is. Though it’s not a simple work so I put it on hold. It would be awesome if someone could help with this.