0

我正在尝试为 plupload 创建一个指令。为了一次一步完成,我首先在不使用指令(控制器和标准 html)的情况下使文件上传工作。然后我添加了指令并成功地让 html 正确呈现。不幸的是,plupload 绑定随后中断了。

乍一看,在 plupload 进行绑定之前,该指令似乎没有呈现,但是如果我在代码中添加日志语句,该指令确实返回了哈希值,并且所有 html 元素似乎都存在于 DOM 中。

关于如何使这项工作的任何想法?

html

<div ng-controller="ProfilePhotoUploader">
    This does not work
    <uploader url="<%= profile_image_uploader_path %>"></uploader>

    This works
    <div id="profile-image-container">
        <div id="select-file">Select File</div>
        <div id="drop-area">Drop file here</div>
        <button class="button small" ng-click="upload('<%= profile_image_uploader_path %>')">Upload File</button>
    </div>
  </div>

上传者.js

var uploader = angular.module('uploader', []);

uploader.directive('uploader', function () {
alert("in directive");
return  {
    restrict: 'E',
    scope: {
        url:'@'
    },
    templateUrl: "/assets/uploader.html"
}
});

资产/uploader.html

<div id="profile-image-container">
  <div id="select-file">Select File</div>
  <div id="drop-area">Drop file here</div>
  <button class="button small" ng-click="upload('{{url}}')">Upload File</button>
</div>

profile_photo_uploader.js

var ProfilePhotoUploader = function ($scope) {

console.log($("uploader"));
$scope.uploader = new plupload.Uploader({
    runtimes: "html5",
    browse_button: 'select-file',
    max_file_size: '10mb',
    container: "profile-image-container",
    drop_element: "drop-area",
    multipart: true,
    multipart_params : {
        authenticity_token: $('meta[name="csrf-token"]').attr('content'),
        _method: 'PUT'
    },
    filters: [
        {title: "Image Files", extensions: "jpg,jpeg,png"}
    ]
});

$scope.upload = function(url) {
    $scope.uploader.settings.url = url;
    $scope.uploader.start();
};

$scope.uploader.init();
};
4

1 回答 1

0

这是该指令的两个版本的小提琴。一个不会创建新的范围。另一个创建一个隔离范围。我发现 ng-click 不能包含 {{}},所以我们需要使用编译函数通过属性参数 (tAttrs) 将 URL 字符串获取到模板中。

没有新的范围。HTML:

<uploader url="http://someplace.com/pic.jpg" upload-fn="upload"></uploader>

指示:

myApp.directive('uploader', function () {
    return {
        restrict: 'E',
        templateUrl: "/assets/uploader.html",
        compile: function (tElement, tAttrs) {
            var buttonElement = tElement.find('button')
            buttonElement.attr('ng-click', tAttrs.uploadFn + "('" + tAttrs.url + "')")
            console.log(tElement.html())
        }
    }
});

上面,该指令使用与控制器相同的作用域,因此 ng-click 属性的值被设置为调用 HTML 中的 upload-fn 属性定义的函数。

upload-fn 属性不是必需的,但它确实使指令更可重用,因为指令被告知要调用什么范围方法——“上传”——因此可以在 HTML 中轻松更改。如果可重用性不是问题,这里有一个更简单的选择:

HTML:

<uploader url="http://someplace.com/pic.jpg"></uploader>

指令变更:

buttonElement.attr('ng-click', "upload('" + tAttrs.url + "')")

隔离范围。HTML:

<uploader-isolate url="http://someplace.com/pic.jpg" upload-fn="upload(url)">
</uploader-isolate>

指示:

myApp.directive('uploaderIsolate', function () {
    return {
        restrict: 'E',
        scope: {
            uploadFn: '&'
        },
        templateUrl: "/assets/uploader.html",
        compile: function (tElement, tAttrs) {
            var buttonElement = tElement.find('button')
            buttonElement.attr('ng-click', "uploadFn({url:'" + tAttrs.url + "'})")
            console.log(tElement.html())
        }
    }
});

上面,该指令创建了一个新的范围——一个隔离范围。这个范围在原型上不是从父/控制器范围继承的,所以它(和指令的模板)不能访问在控制器的 $scope 上定义的 upload() 函数。'&' 符号用于创建“委托”uploadFn 函数。这意味着当“uploadFn”用于隔离作用域时(即,在指令的模板中),它实际上会调用父作用域上的“upload”函数。

此外,我们指定上传函数采用一个参数url。当在指令模板中使用委托函数时,我们不能只传递一个参数。即,这不起作用:uploadFn('http://...')。相反,我们需要使用映射/对象来指定任何参数值。例如,uploadFn({url: 'http://...'})。

隔离范围对象哈希不包含url: '@',因为我认为属性 ng-click 的值不能包含{{}}s。这就是我们使用编译函数并通过编译函数的属性参数获取url属性值的原因。如果 url 值仅在模板中的其他地方使用,例如<span>url = {{url}}</span>,则将使用 '@' 表示法。

修改了模板以删除 ng-click 属性的值。该值被分配给编译函数中的属性。

<button class="button small" ng-click>Upload File</button>
于 2013-01-18T19:11:09.693 回答