Search code examples
angulartypescriptdrag

Drag to move a component around the page?


I am defining a popup dialog box component which will allow a user to input some data to place on the page. The end result is for it to appear when a button on the screen is clicked, and also able to be dragged around the page.

I don't have much of this component yet, here is the code for it:

//edit-global-names-dialog-box.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'edit-global-names-dialog-box',
    templateUrl: './edit-global-names-dialog-box.component.html',
    styleUrls: ['./edit-global-names-dialog-box.component.css']
})
export class EditGlobalNamesDialogBoxComponent implements OnInit{

    constructor() {}

    ngOnInit() {
    }
}

//edit-global-names-dialog-box.component.html

<div id="dialog-box-container">
    <div id="header">

    </div>
    <div id="content">

    </div>
    <div id="footer">

    </div>
</div>

//edit-global-names-dialog-box.component.css

#dialog-box-container {
    height: 12%;
    width: 25%;
    z-index: 2 !important;
    position: absolute;
    background-color: lightgrey;
    right: 50%;
    bottom: 50%;
    transform: translate(45%,-50.1%);
    -moz-box-shadow: 8px 8px 8px #d9d9d9;
    -webkit-box-shadow: 8px 8px 8px #d9d9d9;
    box-shadow: 8px 8px 8px #d9d9d9; 
}

#header {
    border: 0.5px solid dimgrey;
    border-bottom: none;
    height: 20%;
}

#content {
    border: 0.5px solid dimgrey;
    border-bottom: none;
    height: 50%;
}

#footer {
    border: 0.5px solid dimgrey;
    height: 26%;
}

You can see that it's just a template at the moment, a div that appears onto of all other page content, has a shadow and is centered in the page.

Want I want now is to implement a feature whereby when the user clicks and drags on the header div of the dialog box, the entire dialog box is moved around the page.

I have taken a look at a few questions posted previously: Using JS to move a div around the page Make Div Draggable using CSS These suggest pure javascript, or JQuery ways of doing things which I am not sure would mesh well with angular.

How can I enable my component to be dragged around the page?


Solution

  • So the other answer is a great solution for javascript/Jquery, but I've managed to do this in a more angular-y/typescript-y way, with no JQuery. Here it is:

    //edit-global-names-dialog-box.component.html
    
    <div id="dialog-box-container">
        <div id="header"
            (mousedown)="mousedown($event)" 
            (mousemove)="mousemove($event)" 
            (mouseup)="mouseup($event)"
        >
            <div id="title-div">
                <h5 id="title">Edit Global Name</h5>
            </div>
        </div>
        <div id="content">
            <div id="label-area">
    
            </div>
                <input type="text" id="text-box">
        </div>
        <div id="footer">
            <div id="ok-button-div">
                <button type="button" id="ok-button">OK</button>
            </div>
            <div id="cancel-button-div">
                <button type="button" id="cancel-button">Cancel</button>
            </div>
        </div>
    </div>
    

    CSS isn't that important but I'll link it in a fiddle with the HTML if you want to see it, I don't want it taking up space in my answer: FIDDLE

    Here's the angular component:

    //edit-global-names-dialog-box.component.ts
    
    import { Component, OnInit } from '@angular/core';
    
    @Component({
        selector: 'edit-global-names-dialog-box',
        templateUrl: './edit-global-names-dialog-box.component.html',
        styleUrls: ['./edit-global-names-dialog-box.component.css']
    })
    export class EditGlobalNamesDialogBoxComponent implements OnInit{
    
        private mousePosition : PIXI.Point;
        private dragOffset;
        private isDown;
        private dialogBoxDiv;
    
        constructor() {
            this.mousePosition = new PIXI.Point();
            this.isDown = false;
            this.dragOffset = [0, 0];
        }
    
        ngOnInit() {
            this.dialogBoxDiv = document.getElementById('dialog-box-container');
        }
    
        mousedown($event){
            this.isDown = true;
            this.dragOffset = [ 
                this.dialogBoxDiv.offsetLeft - $event.clientX,
                this.dialogBoxDiv.offsetTop - $event.clientY
            ]
        }
    
        mouseup($event){
            this.isDown = false;
        }
    
        mousemove($event){
            $event.preventDefault();
    
            if (this.isDown){
                 var mousePosition = {
                     x : $event.clientX,
                     y : $event.clientY
                 };
    
                 this.dialogBoxDiv.style.left = (mousePosition.x + this.dragOffset[0]) + 'px';
                 this.dialogBoxDiv.style.top  = (mousePosition.y + this.dragOffset[1]) + 'px';
            }
        }
    }
    

    It's a little jittery, but it works mostly well. If anyone has any improvements that can be made, please let me know.