角度拖放(使用 jQuery UI) - 禁用交换

Posted

技术标签:

【中文标题】角度拖放(使用 jQuery UI) - 禁用交换【英文标题】:angular dragdrop (using jQuery UI) - disable swapping 【发布时间】:2016-05-05 02:24:33 【问题描述】:

我在交换拖放的元素时遇到问题。

DOM / Angular 结构:

angular.module('app', ['ngDragDrop'])
.controller('controller', function($scope) 
  $scope.listItems = [
    name: "some name", title: "title",
    name: "some name2", title: "title2",
  ];
  $scope.input = ;
  $scope.draggableOprions = 
    revert: 'invalid'
  
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="https://code.angularjs.org/1.4.9/angular.js"></script>
<script src="https://cdn.jsdelivr.net/angular.dragdrop/1.07/angular-dragdrop.min.js"></script>
<div ng-app="app">
  <div ng-controller="controller">
    <div class="container">
      <ul>
        <li data-drag="true" 
        data-jqyoui-options="draggableOprions" 
        jqyoui-draggable="animate:true" 
        ng-model="item" ng-repeat="item in listItems track by $index">
          item.title
        </li>
      </ul>
    </div>

    <div class="container" 
    data-drop="true" 
    data-jqyoui-options jqyoui-droppable 
    ng-model="input">
      <input ng-model="input.name">
    </div>
  </div>
</div>

问题:

当我拖放一个 list item 1 时,list item 1name 属性属于 input 模型。但在list item 1 中不再可用。实际上,list item 1 的值在我将其放入 input 之后变为 undefined || null。如果我现在尝试在 input 中拖放 list item 2 项目 - 值交换(list item 1 = undefined || null ?list item 2 = list item 1 valueinput 模型等于列表项目 2 值`。所以一切都洗牌。

我需要什么: 我需要在输入中拖放列表项,避免丢失列表项中的值。每次我在输入中删除列表项时,我都需要将它的值绑定到输入。

开箱即用 我可以更改拖放库,甚至使用源代码,但库是更好的选择。我接受几乎所有没有破坏任何良好代码标准的良好工作答案(我的意思是我需要不会破坏其他代码并且具有良好结构的代码)。

【问题讨论】:

【参考方案1】:

我建议使用 ngDraggable,一个不依赖 jQuery 或 jQuery-ui 的 Angular 模块。

以下是一个有效的 sn-p 或查看我的Codepen:

angular.module('app', ['ngDraggable'])
  .controller('controller', function($scope) 

    $scope.listItems = [
      name: "some name",
      title: "title1"
    , 
      name: "some name2",
      title: "title2"
    , 
      name: "some name3",
      title: "title3"
    , ];

    $scope.droppedObjects = [];
    $scope.input = ;
  
    // drag complete over drop area
    $scope.onDragComplete = function(data, evt) 
      console.log("drag success, data:", data);
      var index = $scope.droppedObjects.indexOf(data);
      if (index > -1) 
        $scope.droppedObjects.splice(index, 1);
      
    
    
    // drop complete over drop area
    $scope.onDropComplete = function(data, evt) 
      console.log("drop success, data:", data);
      var index = $scope.droppedObjects.indexOf(data);
      if (index == -1)
        $scope.droppedObjects.push(data);
    
    
    // drop complete over input box
    $scope.onDropCompleteInput = function(data, evt) 
      console.log("drop on input success, data:", data);
      $scope.input = data;
    
    
    // drop complete over items area (remove from dropped list)
    $scope.onDropCompleteRemove = function(data, evt) 
      console.log("drop success - remove, data:", data);
      var index = $scope.droppedObjects.indexOf(data);
      if (index != -1)
        $scope.droppedObjects.splice(index);
    
    
    // other draggable events handlers

    var onDraggableEvent = function(evt, data) 
      console.log("128", "onDraggableEvent", evt, data);
    
    $scope.$on('draggable:start', onDraggableEvent);
    //$scope.$on('draggable:move', onDraggableEvent);
    $scope.$on('draggable:end', onDraggableEvent);
  
  );
* 
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;


[ng-drag] 
  -moz-user-select: -moz-none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;


.item 
  width: 100px;
  height: 60px;
  background: rgba(255, 0, 0, 0.5);
  color: white;
  text-align: center;
  padding-top: 5%;
  display: inline-block;
  margin: 0 10px;
  cursor: move;


ul.draggable-objects:after 
  display: block;
  content: "";
  clear: both;


.draggable-objects li 
  float: left;
  display: block;
  width: 120px;
  height: 100px;


[ng-drag].drag-over 
  border: solid 1px red;


[ng-drag].dragging 
  opacity: 0.5;


.drop-container 
  background: rgba(0, 255, 0, 0.5);
  text-align: center;
  width: 600px;
  height: 200px;
  padding-top: 90px;
  display: block;
  margin: 20px auto;
  position: relative;


.drop-input 
  width: 200px;
  height: 40px;


.drag-enter 
  border: solid 5px red;


.drop-container span.title 
  display: block;
  position: absolute;
  top: 10%;
  left: 50%;
  width: 200px;
  height: 20px;
  margin-left: -100px;
  margin-top: -10px;


.drop-container div 
  position: relative;
  z-index: 2;
<script src="//code.angularjs.org/1.4.8/angular.js"></script>
<script src="//rawgit.com/fatlinesofcode/ngDraggable/master/ngDraggable.js"></script>

<body ng-app="app">
  <div ng-controller="controller">

    <div class="row">
      <h1>ngDraggable Example</h1>
    </div>

    <div ng-drop="true" ng-drop-success="onDropCompleteRemove($data,$event)">
      <ul class="draggable-objects">
        <li ng-repeat="obj in listItems">
          <div ng-drag="true" ng-drag-data="obj" data-allow-transform="true" class="item"> obj.title </div>
        </li>
      </ul>
    </div>

    <hr/>
    <div ng-drop="true" ng-drop-success="onDropComplete($data,$event)" class="drop-container">
      <span class="title">Drop area</span>

      <div ng-repeat="obj in droppedObjects" ng-drag="true" ng-drag-data="obj" ng-drag-success="onDragComplete($data,$event)" class="item">
        obj.title
      </div>
    </div>

    <hr/>
    <div class="container">
      Drop on input:
      <input ng-model="input.name" class="drop-input" ng-drop="true" ng-drop-success="onDropCompleteInput($data,$event)">
    </div>

    <br>
    <hr/>
    <pre>listItems = listItems|json</pre>
    <pre>input = input|json</pre>
    <pre>droppedObjects = droppedObjects|json</pre>
  </div>
</body>

【讨论】:

我真的很喜欢这个库及其行为,但是当我在 angular-bootstrap-ui (Tabs) 中使用它时 - 选项卡标题文本绑定不正确,直到我进行选项卡选择/删除更改。跨度> 你确定吗?我尝试在选项卡式应用程序中添加上面的代码,但看不到任何问题;检查plnkr.co/edit/Z1pMBMOMvUF8ATfKgVzh 是的,我不知道为什么会这样,我现在解决它,但我会尝试修复它。 Actullay uib-tabs 尝试将active 属性设置为ng-drag="true"。它抛出cannot set property 'active' to string 'true'..奇怪.. 如果您可以提供该问题的示例(即 Plunker),我可以帮助您【参考方案2】:
<!DOCTYPE html>
<html>

<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="https://code.angularjs.org/1.4.9/angular.js"></script>
<script src="https://cdn.jsdelivr.net/angular.dragdrop/1.07/angular-dragdrop.min.js"></script>

<body>
    <div ng-app="myApp" ng-controller="MyController">
        <div id="products">
            <h1 class="ui-widget-header">Products</h1>
            <div id="catalog">
                <div>
                    <ul>
                        <li ng-repeat='item in list1' ng-show="item.title" data-drag="true" data-jqyoui-options="revert: 'invalid', helper: 'clone'" ng-model="list1" jqyoui-draggable="index: $index, animate: true, placeholder: 'keep'">item.title</li>
                    </ul>
                </div>
            </div>
        </div> 


    <div id="cart">
        <h1 class="ui-widget-header">Shopping Cart</h1>
        <div class="ui-widget-content">
            <ol data-drop="true" ng-model='list4' jqyoui-droppable="multiple:true">
                <li ng-repeat="item in list4 track by $index" ng-show="item.title" data-drag="true" data-jqyoui-options="revert: 'invalid', helper: 'clone'" ng-model="list4" jqyoui-draggable="index: $index,animate:true">item.title</li>
                <li class="placeholder" ng-hide="hideMe()">Add your items here</li>
            </ol>
        </div>
    </div>

    </div>

<script>
var app = angular.module('myApp', ['ngDragDrop']);

app.controller('MyController', function ($scope,$http,$sce) 

    $scope.list1 = ['title': 'Lolcat Shirt','title': 'Cheezeburger Shirt','title': 'Buckit Shirt'];

    $scope.list4 = [];

    $scope.hideMe = function() 
    
        return $scope.list4.length > 0;
    
);

</script>
</body>
</html>

您必须在 data-jqyoui-options

中使用 helper: 'clone'

【讨论】:

以上是关于角度拖放(使用 jQuery UI) - 禁用交换的主要内容,如果未能解决你的问题,请参考以下文章

使用 jQuery UI 可排序和引导网格复制 Hubspots 拖放表单构建器 UI

HTML 5 拖放相对于 jQuery UI 拖放的优势

jQuery UI 拖放

如何使用角度 cdk v7.0.0+ 在 CdkDropList 中禁用排序

使用jquery ui拖放后的动态div宽度

使用 jquery UI 时如何获取可拖放元素的 id?