【问题标题】:Ember.js: Upload file componentEmber.js:上传文件组件
【发布时间】:2012-12-17 22:13:24
【问题描述】:

我需要创建一个 Ember 组件来选择一个文件。 我的页面将包含多个“上传组件”

我读过一篇试图实现这一点的帖子:(https://stackoverflow.com/questions/9200000/file-upload-with-ember-data) 但是 UploadFileView 直接链接到控制器。 我想要更通用的东西......

我想从视图中删除 App.StoreCardController.set('logoFile'..) 依赖项或从模板中传递字段 (logoFile)...

有改进此代码的想法吗?

   App.UploadFileView = Ember.TextField.extend({
    type: 'file',
    attributeBindings: ['name'],
    change: function(evt) {
      var self = this;
      var input = evt.target;
      if (input.files && input.files[0]) {
        App.StoreCardController.set('logoFile', input.files[0]);
      }
    }
});

和模板:

{{view App.UploadFileView name="icon_image"}}
{{view App.UploadFileView name="logo_image"}}

【问题讨论】:

  • 我确实回复了您的评论顺便说一句-只是为了澄清 UploadFileView 不是控制器,而是一个完整的自定义视图对象。老实说,我认为您可以修改我展示的视图以使其更具动态性并允许您的前端有许多文件上传输入
  • 是的,UploadFileView 是一个完整的视图对象。由于我不是 ember.js 专家,您能否通过示例代码帮助我获得答案?

标签: ember.js


【解决方案1】:

我完成了一个完整的示例来展示这一点

https://github.com/toranb/ember-file-upload

这是基本的车把模板

<script type="text/x-handlebars" data-template-name="person">
{{view PersonApp.UploadFileView name="logo" contentBinding="content"}}
{{view PersonApp.UploadFileView name="other" contentBinding="content"}}
<a {{action submitFileUpload content target="parentView"}}>Save</a>
</script>

这是自定义文件视图对象

PersonApp.UploadFileView = Ember.TextField.extend({
    type: 'file',
    attributeBindings: ['name'],
    change: function(evt) {
      var self = this;
      var input = evt.target;
      if (input.files && input.files[0]) {
        var reader = new FileReader();
        var that = this;
        reader.onload = function(e) {
          var fileToUpload = reader.result;
          self.get('controller').set(self.get('name'), fileToUpload);
        }
        reader.readAsDataURL(input.files[0]);
      }
    }
});

这里是控制器

PersonApp.PersonController = Ember.ObjectController.extend({
  content: null,
  logo: null,
  other: null
});

最后是带有提交事件的视图

PersonApp.PersonView = Ember.View.extend({
  templateName: 'person',
  submitFileUpload: function(event) {
    event.preventDefault();
    var person = PersonApp.Person.createRecord({ username: 'heyo', attachment: this.get('controller').get('logo'), other: this.get('controller').get('other') });
    this.get('controller.target').get('store').commit();
  }
});

如果您启动 django 应用程序,这将在文件系统上删除 2 个文件

【讨论】:

  • 如果我不使用 Person 视图并且 submitFileUpload 有内部控制器,会不会导致问题?对我来说,控制器内部 this.get('logo') 为 null @Toran Billups
  • self.get('controller').set(self.get('name'), fileToUpload);需要改成self.get('targetObject').set(self.get('name'), fileToUpload);
【解决方案2】:

EDIT (2015.06):刚刚创建了一个基于组件的新解决方案。 此解决方案提供了一个带有预览和删除图标的上传按钮。 附言fa 类是 Font Awesome

组件把手

<script type="text/x-handlebars" data-template-name='components/avatar-picker'>
        {{#if content}}
            <img src={{content}}/> <a {{action 'remove'}}><i class="fa fa-close"></i></a>
        {{else}}
            <i class="fa fa-picture-o"></i>
        {{/if}}

        {{input-image fdata=content}}
</script>

组件 JavaScript

App.AvatarPickerComponent = Ember.Component.extend({
    actions: {
        remove: function() {
            this.set("content", null);
        }
    }
});

App.InputImageComponent = Ember.TextField.extend({
    type: 'file',

    change: function (evt) {
        var input = evt.target;
        if (input.files && input.files[0]) {
            var that = this;

            var reader = new FileReader();
            reader.onload = function (e) {
                var data = e.target.result;
                that.set('fdata', data);
            };
            reader.readAsDataURL(input.files[0]);
        }
    }
});

使用示例

{{avatar-picker content=model.avatar}}

旧答案

我以 Chris Meyers 为例,我把它变小了。

模板

{{#view Ember.View contentBinding="foto"}}
    {{view App.FotoUp}}
    {{view App.FotoPreview width="200" srcBinding="foto"}}
{{/view}}

JavaScript

App.FotoPreview= Ember.View.extend({
    attributeBindings: ['src'],
    tagName: 'img',
});


App.FotoUp= Ember.TextField.extend({
    type: 'file',

    change: function(evt) {
        var input = evt.target;
        if (input.files && input.files[0]) {
            var that = this;

            var reader = new FileReader();
            reader.onload = function(e) {
                var data = e.target.result;
                that.set('parentView.content', data);
            }
            reader.readAsDataURL(input.files[0]);
        }
    },
});

【讨论】:

  • 这样我只能将图像的二进制数据发送到服务器。不得不为服务器端做很多修复。无论如何我可以为rails服务器(Carrierwave)发送整个文件对象(临时文件)吗??
  • 如果要使用multipart-formdata,可以在form上使用jQuery的.serialize()方法。
【解决方案3】:

Marek Fajkus 你不能使用 JQuery 的 .serialize,它在 JQuery UI docs 的文档中没有提到文件上传

但是,您可以使用JQuery Upload Plugin

实际上它确实提到了它,它说: “。来自文件选择元素的数据未序列化。”

【讨论】:

    【解决方案4】:

    在上传多个文件的情况下,您可能需要使用

    {{input type='file' multiple='true' valueBinding='file'}}
                              ^^^^
    

    这是您在正常的 HTML 上传中使用的解决方案。

    此外,您可以使用'valueBinding',它允许您针对组件中的该值设置观察者。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-18
      • 2012-10-12
      • 1970-01-01
      • 2014-06-16
      • 1970-01-01
      • 2019-02-16
      • 2015-08-31
      • 2017-05-12
      相关资源
      最近更新 更多