【问题标题】:How to Create simple drag and Drop in angularjs如何在angularjs中创建简单的拖放
【发布时间】:2013-09-01 05:04:30
【问题描述】:

我想知道如何使用 AngularJs 进行拖放。

这是我目前所拥有的:

<span><input type="checkbox" ng-model="master"><span>SelectAll</span></span>
<div ng-repeat="todo in todos">

    <div ng-hide="enableEditor">
        <a href="#">Drag</a>
        <input id="checkSlave" type="checkbox" ng-checked="master" ng-model="todo.done">

        <span ng-if="checked" ng-show="removed" ng-bind="todo.task_name" class="removed"></span>
        <span ng-bind="todo.task_name"></span>
        <span ng-bind="todo.state"></span>
        <a href="#" ng-click="editTask(todo.task_id,todo.task_name,editMode=!editMode)">Edit</a> 

       </div>
       </div>

    <div ng-show="enableEditor">
     <input type="text" ng-show="editMode" ng-model="todo.task_name"  ng-change="update(todo.task_id,todo.task_name)">
     <a href="#" ng-click="saveTask(todo.task_id,todo.task_name,editMode=!editMode)">Save</a>
     <a href="#" ng-click="cancelTask(todo.task_id,todo.task_name,editMode=!editMode)">Cancel</a>
    </div>
</div>

http://plnkr.co/edit/llTH9nRic3O2S7XMIi6y?p=preview..

【问题讨论】:

标签: javascript angularjs angularjs-directive


【解决方案1】:

我刚刚将这个发布到我的品牌新博客: http://jasonturim.wordpress.com/2013/09/01/angularjs-drag-and-drop/

这里的代码: https://github.com/logicbomb/lvlDragDrop

在这里演示:http://logicbomb.github.io/ng-directives/drag-drop.html

这些指令依赖于我在下面包含的 UUID 服务:

var module = angular.module("lvl.directives.dragdrop", ['lvl.services']);

module.directive('lvlDraggable', ['$rootScope', 'uuid', function($rootScope, uuid) {
        return {
            restrict: 'A',
            link: function(scope, el, attrs, controller) {
                console.log("linking draggable element");

                angular.element(el).attr("draggable", "true");
                var id = attrs.id;
                if (!attrs.id) {
                    id = uuid.new()
                    angular.element(el).attr("id", id);
                }

                el.bind("dragstart", function(e) {
                    e.dataTransfer.setData('text', id);

                    $rootScope.$emit("LVL-DRAG-START");
                });

                el.bind("dragend", function(e) {
                    $rootScope.$emit("LVL-DRAG-END");
                });
            }
        }
    }]);

module.directive('lvlDropTarget', ['$rootScope', 'uuid', function($rootScope, uuid) {
        return {
            restrict: 'A',
            scope: {
                onDrop: '&'
            },
            link: function(scope, el, attrs, controller) {
                var id = attrs.id;
                if (!attrs.id) {
                    id = uuid.new()
                    angular.element(el).attr("id", id);
                }

                el.bind("dragover", function(e) {
                  if (e.preventDefault) {
                    e.preventDefault(); // Necessary. Allows us to drop.
                  }

                  e.dataTransfer.dropEffect = 'move';  // See the section on the DataTransfer object.
                  return false;
                });

                el.bind("dragenter", function(e) {
                  // this / e.target is the current hover target.
                  angular.element(e.target).addClass('lvl-over');
                });

                el.bind("dragleave", function(e) {
                  angular.element(e.target).removeClass('lvl-over');  // this / e.target is previous target element.
                });

                el.bind("drop", function(e) {
                  if (e.preventDefault) {
                    e.preventDefault(); // Necessary. Allows us to drop.
                  }

                  if (e.stopPropagation) {
                    e.stopPropagation(); // Necessary. Allows us to drop.
                  }
                    var data = e.dataTransfer.getData("text");
                    var dest = document.getElementById(id);
                    var src = document.getElementById(data);

                    scope.onDrop({dragEl: src, dropEl: dest});
                });

                $rootScope.$on("LVL-DRAG-START", function() {
                    var el = document.getElementById(id);
                    angular.element(el).addClass("lvl-target");
                });

                $rootScope.$on("LVL-DRAG-END", function() {
                    var el = document.getElementById(id);
                    angular.element(el).removeClass("lvl-target");
                    angular.element(el).removeClass("lvl-over");
                });
            }
        }
    }]);

UUID 服务

angular
.module('lvl.services',[])
.factory('uuid', function() {
    var svc = {
        new: function() {
            function _p8(s) {
                var p = (Math.random().toString(16)+"000000000").substr(2,8);
                return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ;
            }
            return _p8() + _p8(true) + _p8(true) + _p8();
        },

        empty: function() {
          return '00000000-0000-0000-0000-000000000000';
        }
    };

    return svc;
});

【讨论】:

  • 我在 Angular 1.2.6 中遇到此代码错误。 “多个指令 [lvlDropTarget, tooltip] 要求新的/隔离的范围:
  • 我认为这里的stopPropogation 应该是stopPropagation。由于少于 6 个字符,因此无法自己进行编辑:/
  • @AndrewMagee 已经在github更新了-github.com/logicbomb/lvlDragDrop
  • 为什么你的属性名称以x- 开头,而指令名称却没有?
  • 如果包含 jQuery 并且您收到 "Cannot call method 'setData' of undefined" 错误。使用e.originalEvent.dataTransfer 而不是e.dataTransfer
【解决方案2】:

Angular 不提供诸如拖放之类的时髦 UI 元素。这并不是 Angular 的真正目的。但是,有一些众所周知的指令提供拖放功能。这是我用过的两个。

https://github.com/angular-ui/ui-sortable

https://github.com/codef0rmer/angular-dragdrop

【讨论】:

  • 你有什么建议?
【解决方案3】:

我参加聚会有点晚了,但我有自己的指令,看起来很适合你的情况(你可以自己调整)。它是对 ng-repeat 指令的修改,专门为通过 DnD 进行列表重新排序而构建。我构建它是因为我不喜欢 JQuery UI(比其他任何东西都更喜欢更少的库),我也希望我的也能在触摸屏上工作;)。

代码在这里:http://codepen.io/SimeonC/pen/AJIyC

博文在此:http://sdevgame.wordpress.com/2013/08/27/angularjs-drag-n-drop-re-order-in-ngrepeat/

【讨论】:

    【解决方案4】:

    修改自angular-drag-and-drop-lists examples page

    标记

    <div class="row">
        <div ng-repeat="(listName, list) in models.lists" class="col-md-6">
            <ul dnd-list="list">
                <li ng-repeat="item in list" 
                    dnd-draggable="item" 
                    dnd-moved="list.splice($index, 1)" 
                    dnd-effect-allowed="move" 
                    dnd-selected="models.selected = item" 
                    ng-class="{'selected': models.selected === item}" 
                    draggable="true">{{item.label}}</li>
            </ul>
        </div>
    </div>
    

    角度

    var app = angular.module('angular-starter', [
        'ui.router',
        'dndLists'
    ]);
    
    app.controller('MainCtrl', function($scope){
    
        $scope.models = {
            selected: null,
            lists: {"A": [], "B": []}
        };
    
        // Generate initial model
        for (var i = 1; i <= 3; ++i) {
            $scope.models.lists.A.push({label: "Item A" + i});
            $scope.models.lists.B.push({label: "Item B" + i});
        }
    
        // Model to JSON for demo purpose
        $scope.$watch('models', function(model) {
            $scope.modelAsJson = angular.toJson(model, true);
        }, true);
    });
    

    可以通过 bower 或 npm 安装库:angular-drag-and-drop-lists

    【讨论】:

    • 这太棒了。它具有所有功能
    • 谢谢你,文档上不清楚 :) 这更容易 :)
    • 通过npm安装后如何将其包含在我的项目中
    • @MMR 您可以通过以下方式进行操作:angular.module("demo", ["dndLists"]); 将“demo”替换为您的应用名称。将 angular-drag-and-drop-lists.min.js 添加到 HTML 文件中的脚本标记。应该这样做。
    【解决方案5】:

    adapt-strap 有非常轻量级的模块。 这是fiddle。 以下是一些受支持的属性。还有更多。

    ad-drag="true"
    ad-drag-data="car"
    ad-drag-begin="onDragStart($data, $dragElement, $event);"
    ad-drag-end="onDataEnd($data, $dragElement, $event);"
    

    【讨论】:

      【解决方案6】:

      用于按角度拖放的小脚本

      (function(angular) {
        'use strict';
      angular.module('drag', []).
        directive('draggable', function($document) {
          return function(scope, element, attr) {
            var startX = 0, startY = 0, x = 0, y = 0;
            element.css({
             position: 'relative',
             border: '1px solid red',
             backgroundColor: 'lightgrey',
             cursor: 'pointer',
             display: 'block',
             width: '65px'
            });
            element.on('mousedown', function(event) {
              // Prevent default dragging of selected content
              event.preventDefault();
              startX = event.screenX - x;
              startY = event.screenY - y;
              $document.on('mousemove', mousemove);
              $document.on('mouseup', mouseup);
            });
      
            function mousemove(event) {
              y = event.screenY - startY;
              x = event.screenX - startX;
              element.css({
                top: y + 'px',
                left:  x + 'px'
              });
            }
      
            function mouseup() {
              $document.off('mousemove', mousemove);
              $document.off('mouseup', mouseup);
            }
          };
        });
      })(window.angular);
      

      source link

      【讨论】:

        【解决方案7】:

        使用 HTML 5 拖放
        您可以使用 HTML 5 拖放功能和角度指令轻松存档。

        1. 通过设置 draggable = true 来启用拖动。
        2. 为父容器和子项添加指令。
        3. 覆盖拖放功能 - 'ondragstart' 用于父级,'ondrop' 用于子级。

        找到下面的示例,其中list 是项目数组。
        HTML 代码:

            <div class="item_content" ng-repeat="item in list" draggrble-container>
                <div class="item" draggable-item draggable="true">{{item}}</div>
            </div>
        

        Javascript:

            module.directive("draggableItem",function(){
             return {
              link:function(scope,elem,attr){
                elem[0].ondragstart = function(event){
                    scope.$parent.selectedItem = scope.item;
                };
              }
             };
            });
        
        
            module.directive("draggrbleContainer",function(){
             return {
                link:function(scope,elem,attr){
                    elem[0].ondrop = function(event){
                        event.preventDefault();
                        let selectedIndex = scope.list.indexOf(scope.$parent.selectedItem);
                        let newPosition = scope.list.indexOf(scope.item);
                        scope.$parent.list.splice(selectedIndex,1);
                        scope.$parent.list.splice(newPosition,0,scope.$parent.selectedItem);
                        scope.$apply();
                    };
                    elem[0].ondragover = function(event){
                        event.preventDefault();
        
                    };
                }
             };
            });
        

        在这里找到完整的代码https://github.com/raghavendrarai/SimpleDragAndDrop

        【讨论】:

        • 'ondrop' 功能不会为我触发。
        猜你喜欢
        相关资源
        最近更新 更多
        热门标签