AngularJS文件拖放指令

Posted

技术标签:

【中文标题】AngularJS文件拖放指令【英文标题】:AngularJS file drag and drop in directive 【发布时间】:2013-01-20 16:06:09 【问题描述】:

这个例子做了很多我想在 Angular-js 中移植的东西:html5 File API。

我一直在尝试在 Google 上搜索一些指令示例,但我发现旧示例大量使用 DOM 或不是为 Angular 1.0.4 编写的。

基本上这是纯js代码:

var holder = document.getElementById('holder'),
    state = document.getElementById('status');

if (typeof window.FileReader === 'undefined') 
  state.className = 'fail';
 else 
  state.className = 'success';
  state.innerHTML = 'File API & FileReader available';


holder.ondragover = function ()  this.className = 'hover'; return false; ;
holder.ondragend = function ()  this.className = ''; return false; ;
holder.ondrop = function (e) 
  this.className = '';
  e.preventDefault();

  var file = e.dataTransfer.files[0],
      reader = new FileReader();
  reader.onload = function (event) 
    console.log(event.target);
    holder.style.background = 'url(' + event.target.result + ') no-repeat center';
  ;
  console.log(file);
  reader.readAsDataURL(file);

  return false;
;

我能想到的唯一可能的方法是创建一个指令

edo.directive('fileDrag', function () 
  return 
    restrict: 'A',
    link: function (scope, elem) 
      elem.bind('ondrop', function(e)
        e.preventDefault();
        var file = e.dataTransfer.files[0], reader = new FileReader();
          reader.onload = function (event) 
          console.log(event.target);
          holder.style.background = 'url(' + event.target.result + ') no-repeat center';
        ;
        console.log(file);
        reader.readAsDataURL(file);

        return false;
      );
    
  ;
);

但是(1)它不起作用,(2)在我修复它之前我想知道是否存在某些东西或者我是否正确地做,

非常感谢任何提示或帮助。

【问题讨论】:

有什么不好的地方? 显然 elem.bind('drop') 不起作用。 :// 据此:***.com/questions/9544977/… 您需要在其他两个拖动事件中防止默认值。在此答案中粘贴的示例中,只需将$('#div') 替换为element 我还推荐使用on 而不是绑定。它的工作方式与绑定相同。 .on 是否包含在 Angular 中? 哦,是的,我想不是,在这种情况下,继续bind :) 【参考方案1】:

要将 cmets 合并为答案,请将 ondrop 更改为 drop,添加 e.stopPropagation(),将 holder 更改为 elem

edo.directive('fileDrag', function () 
  return 
    restrict: 'A',
    link: function (scope, elem) 
      elem.bind('drop', function(e)
        e.preventDefault();
        e..stopPropagation();
        var file = e.dataTransfer.files[0], reader = new FileReader();
          reader.onload = function (event) 
          console.log(event.target);
          elem.style.background = 'url(' + event.target.result + ') no-repeat center';
        ;
        console.log(file);
        reader.readAsDataURL(file);

        return false;
      );
    
  ;
);

我正在做类似的事情,这是我的工作解决方案:

HTML

app.directive("dropzone", function() 
    return 
        restrict : "A",
        link: function (scope, elem) 
            elem.bind('drop', function(evt) 
                evt.stopPropagation();
                evt.preventDefault();

                var files = evt.dataTransfer.files;
                for (var i = 0, f; f = files[i]; i++) 
                    var reader = new FileReader();
                    reader.readAsArrayBuffer(f);

                    reader.onload = (function(theFile) 
                        return function(e) 
                            var newFile =  name : theFile.name,
                                type : theFile.type,
                                size : theFile.size,
                                lastModifiedDate : theFile.lastModifiedDate
                            

                            scope.addfile(newFile);
                        ;
                    )(f);
                
            );
        
    
);
div[dropzone] 
    border: 2px dashed #bbb;
    border-radius: 5px;
    padding: 25px;
    text-align: center;
    font: 20pt bold;
    color: #bbb;
    margin-bottom: 20px;
<div dropzone>Drop Files Here</div>

【讨论】:

不,Dropzone 不能很好地处理 angular 我刚刚使用你的代码创建了一个 plnkr,但我没有运气。你能帮忙指出它有什么问题吗?plnkr.co/edit/C7Vv8d?p=preview 谢谢。我知道这是一篇较旧的帖子,但开箱即用我只有一个问题。获取文件信息我不得不遍历有点不同。 var files = evt.dataTransfer.files; Change To var files = evt.originalEvent.dataTransfer.files 非常感谢您的解决方案。 为了在 Chrome 中正常工作,您现在需要阻止“dragover”事件的默认设置。您可以使用这样的代码:element.bind('dragover', ($event) => $event.preventDefault() $event.stopPropagation() )【参考方案2】:

防止默认事件,并从原始事件中获取文件。都可以在指令中实现。您应该传递函数,用于处理文件以属性 on-file-drop。拖动时还将“拖动”类添加到 dropzone 元素。 在视图中它看起来像这样:

<div file-dropzone on-file-drop="myFunction">This is my dropzone </div>

指令:

function fileDropzoneDirective() 
    return 
        restrict: 'A',
        link: fileDropzoneLink
    ;
    function fileDropzoneLink($scope, element, attrs) 
        element.bind('dragover', processDragOverOrEnter);
        element.bind('dragenter', processDragOverOrEnter);
        element.bind('dragend', endDragOver);
        element.bind('dragleave', endDragOver);
        element.bind('drop', dropHandler);

        function dropHandler(angularEvent) 

            var event = angularEvent.originalEvent || angularEvent;
            var file = event.dataTransfer.files[0];
            event.preventDefault();
            $scope.$eval(attrs.onFileDrop)(file);

        
        function processDragOverOrEnter(angularEvent) 
            var event = angularEvent.originalEvent || angularEvent;
            if (event) 
                event.preventDefault();
            
            event.dataTransfer.effectAllowed = 'copy';
            element.addClass('dragging');
            return false;
        

        function endDragOver() 
            element.removeClass('dragging');
        
    

【讨论】:

这是一个很好的答案。只有一件事,我不得不在 dropHandler 的末尾调用 endDragOver 来消除文件处理后的拖动效果。

以上是关于AngularJS文件拖放指令的主要内容,如果未能解决你的问题,请参考以下文章

在 AngularJS 应用程序中拖放的自定义指令

如何使用angularJS突出显示可拖动元素下的拖放区?

在angularjs中对表格的行进行排序或重新排列(拖放)

Angular js/MVC 中的文件拖放功能不起作用

AngularJS - 使用 angularjs 拖放列表库时在 html 页面中没有得到任何东西

嵌套 ng-repeat 拖放,AngularJS