AngularJS plupload指令绑定问题

时间:2012-12-30 00:27:08

标签: angularjs

我正在尝试为plupload创建一个指令。为了一步一步,我首先让文件上传工作而不使用指令(controller和std 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>

uploader.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();
};

1 个答案:

答案 0 :(得分:0)

这是一个带有两个版本指令的fiddle。一个人没有创建新的范围。另一个创建了隔离范围。我发现ng-click不能包含{{}},因此我们需要使用编译函数通过attributes参数(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())
        }
    }
});

在上面,该指令创建了一个新范围 - isolate 范围。此范围不是从父/控制器范围原型继承,因此它(和指令的模板)无权访问控制器$ scope上定义的upload()函数。 '&amp;'表示法用于创建“委托”uploadFn函数。这意味着当在隔离范围中使用“uploadFn”时(即在指令的模板中),它实际上将在父范围上调用“upload”函数。

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

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

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

<button class="button small" ng-click>Upload File</button>