Ember.js: Загрузить файл

Мне нужно создать компонент Ember для выбора файла. Моя страница будет содержать несколько компонентов загрузки

Я прочитал сообщение, пытающееся реализовать это: (qaru.site/info/258635/...), но 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"}}

Ответ 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
});

И, наконец, вот представление w/submit event

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

Ответ 2

EDIT (2015.06): просто создано новое решение на основе компонента. Это решение обеспечивает кнопку загрузки с предварительным просмотром и удалением значка. Постскриптум Классы fa Шрифт 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]);
        }
    },
});

Ответ 3

Marek Fajkus вы не можете использовать JQuery.serialize, он не упоминает о загрузке файлов в документации JQuery UI docs

Однако вы можете использовать JQuery Upload Plugin

На самом деле он упоминает об этом, он говорит: "Данные из элементов выбора файлов не сериализованы".

Ответ 4

В случае загрузки нескольких файлов вы можете использовать

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

Это решение, которое вы использовали бы при обычной загрузке HTML.

Кроме того, вы можете использовать 'valueBinding', который позволит вам настроить наблюдателя против этого значения в вашем компоненте.