【问题标题】:How to make Bootstrap modal popup as movable in Angular2如何使 Bootstrap 模态弹出窗口在 Angular2 中可移动
【发布时间】:2017-12-30 02:12:00
【问题描述】:

我的 Angular2 应用程序中有一个 Bootstrap 模式弹出窗口。我希望它是可拖动的。如果有人可以帮助我解决此问题,那将非常有帮助。

<div class="modal modal-sm fade fade in" [class]="modalWorkPhone" id="myModal" role="dialog">
   <div class="modal-dialog"> 
   <!-- Modal content-->
     <div class="modal-content">
       <div class="panel-heading" style="background-color:#2e90bd">
       </div>
     </div>
   </div>
</div>

【问题讨论】:

    标签: twitter-bootstrap angular angular2-template


    【解决方案1】:

    以下指令代码适用于 Angular 6+ 和来自 ng-bootstrap 库的模式窗口。

    您必须使该指令对您的视图模块可见,并且所有模式都将变为可拖动而无需任何更改,因为该指令绑定到 .modal-header 类:

    import { Directive, ElementRef, Renderer2, AfterViewInit, Input, OnDestroy } from '@angular/core';
    import { fromEvent, Subscription } from 'rxjs';
    import { mergeMap, takeUntil, tap } from 'rxjs/operators';
    
    interface Point {x: number, y: number};
    
    @Directive({
      selector: '.modal-header'
    })
    export class DragModalDirective implements AfterViewInit, OnDestroy  {
    
      constructor (
        private el: ElementRef,
        private renderer: Renderer2,
      ) {}
    
      subscription: Subscription;
    
      start: Point;
      offset: Point = {x: 0, y: 0};
    
      ngAfterViewInit() {       
    
        setTimeout(() => {
          this.makeItDraggable();      
        });
    
      }  
    
      private makeItDraggable() {
    
        const modalDialogElement = this.el.nativeElement.closest(".modal-dialog");
    
        if (!modalDialogElement) {
          console.error('DragModalDirective cannot find the parent element with class modal-dialog')
          return;
        }
    
        this.renderer.setStyle(this.el.nativeElement, 'user-select', 'none');
        this.renderer.setStyle(this.el.nativeElement, 'cursor', 'move'); 
    
        this.renderer.setStyle(modalDialogElement, 'transition', 'none');
    
        const down$ = fromEvent(this.el.nativeElement, 'mousedown')
        const move$ = fromEvent(document, 'mousemove');
        const up$ = fromEvent(document, 'mouseup')
    
        const drag$ = down$.pipe(        
          tap(($event: MouseEvent) => {
            this.start = {
              x: $event.clientX - this.offset.x, 
              y: $event.clientY - this.offset.y
            };
          }),
          mergeMap(down => move$.pipe(
            takeUntil(up$)
          ))
        );
    
        this.subscription = drag$.subscribe(($event: MouseEvent) => {
          this.offset = {
            x: $event.clientX - this.start.x,
            y: $event.clientY - this.start.y
          }
    
         this.renderer.setStyle(modalDialogElement, 'transform', `translate(${this.offset.x}px, ${this.offset.y}px)`);
        }) 
      }
    
      ngOnDestroy() {
        if (this.subscription)
          this.subscription.unsubscribe();
      } 
    }
    

    【讨论】:

    • 不错,也适用于最新的 Angular 11。
    【解决方案2】:

    https://gist.github.com/markleusink/7af171d5f17e7dc9714e69965fdabab9 上的这种方法启发了我

    我稍微修改了一下,结果如下:

    通过将draggable 添加到您的模态标题&lt;div class="modal-header" draggable&gt; &lt;/div&gt; 来使用它

    import { Directive, ElementRef, HostListener, AfterViewInit } from '@angular/core';
    
    /*
     * Directive to add 'drag' support to Ngx Bootstrap modals (https://github.com/valor-software/ngx-bootstrap).
     * Based on this library to enable drag support for an ng-bootstrap modal: https://github.com/mattxu-zz/ngb-modal-draggable
     *
     * Enable by adding the directive to the modal-header element, e.g.:
     * <div class="modal-header" draggable>  </div>
     */
    
    @Directive({
        selector: '[draggable]'
    })
    
    export class DraggableDirective implements AfterViewInit {
        private modalElement: HTMLElement;
        private topStart: number;
        private leftStart: number;
        private isDraggable: boolean;
        private handleElement: HTMLElement;
    
        constructor(public element: ElementRef) {}
    
        public ngAfterViewInit() {
            let element = this.element.nativeElement;
    
            //only make the modal header draggable
            this.handleElement = this.element.nativeElement;
    
            //change cursor on the header
            this.handleElement.style.cursor = 'move';
    
            //get the modal parent container element: that's the element we're going to move around
            for (let level = 3; level > 0; level--) {
                element = element.parentNode;
            }
    
            this.modalElement = element;
            this.modalElement.style.position = 'relative';
        }
    
        @HostListener('mousedown', ['$event'])
        public onMouseDown(event: MouseEvent) {
            if (event.button === 2 || !this.handleElement) {
                return; // prevents right click drag or initialized handleElement
            }
    
            if (event.target !== this.handleElement && !this.searchParentNode(<any>event.target, this.handleElement)) {
                return; // prevents dragging of other elements than children of handleElement
            }
    
            //enable dragging
            this.isDraggable = true;
    
            //store original position
            this.topStart = event.clientY - Number(this.modalElement.style.top.replace('px', ''));
            this.leftStart = event.clientX - Number(this.modalElement.style.left.replace('px', ''));
            event.preventDefault();
        }
    
        @HostListener('document:mouseup', ['$event'])
        public onMouseUp(event: MouseEvent) {
            this.isDraggable = false;
        }
    
        @HostListener('document:mousemove', ['$event'])
        public onMouseMove(event: MouseEvent) {
            if (this.isDraggable) {
                //on moving the mouse, reposition the modal
                this.modalElement.style.top = (event.clientY - this.topStart) + 'px';
                this.modalElement.style.left = (event.clientX - this.leftStart) + 'px';
            }
        }
    
        @HostListener('document:mouseleave', ['$event'])
        public onMouseLeave(event: MouseEvent) {
            this.isDraggable = false;
        }
    
        private searchParentNode(element: Node, tag: Node): Node {
            while (element.parentNode) {
                element = element.parentNode;
                if (element === tag) {
                    return element;
                }
            }
    
            return null;
        }
    
    }
    

    【讨论】:

    • 感谢迈克尔的回答。它对我有用。
    【解决方案3】:

    我有相同的用户请求并通过使用 npm 模块“angular-draggable”解决了它。只需按照说明安装并将draggable="true" 属性添加到您的模态div。

    【讨论】:

      猜你喜欢
      • 2014-03-28
      • 2016-01-23
      • 1970-01-01
      • 1970-01-01
      • 2014-02-22
      • 1970-01-01
      • 2016-09-26
      • 2017-07-18
      • 1970-01-01
      相关资源
      最近更新 更多