2012-12-17 55 views
10

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

我已阅读一篇文章,试图实现:(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"}} 
+0

我回复了您的评论btw - 并且只是为了澄清UploadFileView不是控制器,而是一个完整的自定义视图目的。老实说,我认为你可以修改我所展示的视图,使其更具动态性,并允许你的前端拥有多个文件上传输入 –

+0

是的,UploadFileView是一个全视图对象。由于我不是一名ember.js专家,你能帮我用示例代码得到答案吗? – fvisticot

回答

13

我完成了一个完整的例子以行动表达这种

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 
}); 

最后这里是视图W /提交事件

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

这将砸在2档文件系统,如果你旋转了Django应用程序

+0

如果我不使用Person视图并且submitFileUpload内部有控制器,可能会导致问题吗?对于我内部控制器this.get('logo')为null @Toran Billups – Nininea

+1

'self.get('controller').set(self.get('name'),fileToUpload);'需要改为'self .get('targetObject')。set(self.get('name'),fileToUpload);' – Roel

10

编辑(2015.06):刚刚创建了一个基于组件的新解决方案。 该解决方案提供了一个预览和删除图标的上传按钮。 P.S.的faFont 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]); 
     } 
    }, 
}); 
+0

这对我所需要的很好用 – jakecraige

+0

这样我只能发送图像的二进制数据到服务器。必须为服务器端做很多修复。无论如何,我可以发送整个文件对象(临时文件)的轨道服务器(Carrierwave)? – Abhaya

+0

如果你想使用multipart-formdata,你可以在表单上使用jQuery的.serialize()方法。 –

0

马立克Fajkus你不能使用jQuery的.serialize,它使得在JQuery UI docs

但是文档中没有提及文件上传的,你可以使用JQuery Upload Plugin

其实它提到它,它说: “。从文件中的数据选择元素不是序列。”

0

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

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

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

此外,您可以使用'valueBinding',这将允许您设置一个观察者在您的组件中的值。