我正在使用这个漂亮的Ember.js mixin:https://github.com/Wildhoney/EmberDroplet来使用拖放功能上传图像,并且它的工作非常出色。
唯一的问题是,我不知道如何在上传后将图像添加到视图中。该模型在我的Rails API中正确更新,但是,如果没有实际刷新整个页面,我不知道如何在Ember中更新模型。
以下是我的代码的一些片段:
router.js.coffee
App.Router.map ->
@resource('site', { path: '/' }, ->
@resource('media')
)
routes.js.coffee
App.MediaRoute = Ember.Route.extend
model: (params)->
return App.Media.find()
media.handlebars
<div class="row">
<div id="media-container" class="large-12">
<div class="row">
{{#each media in model}}
<div class="large-4 columns">
<a class="th" {{bind-attr href='media.url'}}>
<img {{bind-attr src='media.thumb'}}>
</a>
</div>
{{else}}
<div class="large-12">
<p>Sorry, no images to display.</p>
</div>
{{/each}}
</div>
</div><!-- /#media-container -->
</div><!-- /.row -->
<div class="row">
<div id="media-upload" class="large-12">
<div class="buttons">
<button class="btn" {{action "uploadAllFiles"}}>Upload All</button>
<button class="btn" {{action "clearAllFiles"}}>Clear</button>
</div>
{{#if uploadStatus.uploading}}
<h3 class="uploading-percentage">Uploaded Percentage: {{uploadStatus.percentComplete}}%</h3>
{{/if}}
{{#view view.DragDrop}}
{{#if uploadStatus.error}}
<div class="error">An error occurred during the upload process. Please try again later.</div>
{{/if}}
{{#each controller.validFiles}}
<div {{bind-attr class="className:image"}}>
{{name}}
<a class="remove" {{action "deleteFile" this}}>Discard.</a>
{{view view.ImagePreview imageBinding="this"}}
</div>
{{/each}}
{{view view.MultipleInput}}
{{/view}}
</div><!-- /#media-upload -->
</div><!-- /.row -->
media.js
App.MediaController = Ember.ArrayController.extend(DropletController, {
dropletUrl: 'http://localhost:3000/images',
uploadedSomeFiles: function uploadedSomeFiles() {
var files = this.get('uploadedFiles');
files.forEach(function(file) {
// This gets fired every-time a file has uploaded successfully
console.log(file + ' was uploaded!');
});
}.observes('files.length', 'files.@each.uploaded')
});
哦,是的,模型,如果有帮助(我使用的是ember模型):
App.Site = Ember.Model.extend({
title: attr(String),
about_text: attr(String),
is_custom_domain: attr(Boolean),
subdomain: attr(String),
url: attr(String),
copyright: attr(String),
site_desc: attr(String),
meta_keywords: attr(String),
footer_code: attr(String),
header_code: attr(String),
hide_site: attr(Boolean),
user: belongsTo('App.User', {key: 'user_id'}),
page: hasMany('App.Page', {key: 'pages', embedded: true}),
media: hasMany('App.Media', {key: 'images', embedded: true})
});
App.Media = Ember.Model.extend({
file_size: attr(Number),
width: attr(Number),
height: attr(Number),
url: attr(String),
identifier: attr(String),
current_path: attr(String),
content_type: attr(String),
thumb: attr(String),
medium: attr(String),
small: attr(String),
tall_banner: attr(String),
short_banner: attr(String),
site: belongsTo('App.Site', {key: 'site_id'})
});
单独使用jQuery,将新图像附加到页面上会很简单,但由于某些原因,Ember使它变得非常复杂。 (好吧,平心而论,Ember的其他事情要容易得多。)
更新:
难道你不知道吗,我把问题困扰了好几天(是的,几天)和几个小时后我把它发布到stackoverflow,我接近答案了。
我发现由于emberdroplet使用标准的XMLHttpRequest,我可以使用request.onload并访问我的Rails API发回的request.responseText。
好的,现在这是我的代码:
request.onload = function() {
var media = App.Media.find();
request.responseText.forEach(function(file, media) {
media.pushObject(file);
console.log(file.id);
});
}
但是,我收到了一个错误:
我回来了这个JSON:
{"id":93,"file_size":438162.0,"width":null,"height":null,"url":"/uploads/image/image/93/blevins_header_2013_v6.jpg", etc.
并将其添加到视图中:
<a class="th" data-bindattr-276="276">
<img data-bindattr-278="278">
</a>
所以,我想,Ember模型不知道如何处理原始JSON,所以我应该先做点什么,对吗?
有什么想法吗?
答案 0 :(得分:0)
您需要在服务器端创建新媒体模型后获取它。方法取决于你。
例如,您可以每次调用this.store.find('media')
来获取所有模型。
或者设置MediaRoute.model
以返回this.store.filter('media')
并添加服务器端路由以创建媒体模型。然后在客户端上,您需要为每个上传的文件手动创建一个新模型并保存它们(ember-data会自动将它们插入到过滤的数组中)。
或者你可以自己处理所有的ajax工作。如果你想要一个简单的jQuery方式,将模板绑定到{{#each file in files}}
,它会迭代上传的文件(使用file.url或smth,我不确定)。要加载已上传的文件,请使用$.getJSON
方法并将响应中的每个文件添加到MediaController.files
属性中(我不推荐这种方式,但可能很简单)。
答案 1 :(得分:0)
好的,所以我终于弄明白了。也许不是最好的方式,但这里也是。
其中一个主要障碍是发现mixin没有为我的rails后端提供类似数组的名称。用他的话说:
Node.js足以巧妙地推断出一系列图像,而 Ruby / PHP需要指定类似数组的名称。
开发人员非常友好地添加了这个。 (见本提交:https://github.com/Wildhoney/EmberDroplet/commit/c769268084a006704f68f6993bb999e796762e4e)
所以,这是我完整的MediaController
代码,适用于任何使用此类事情的人。
App.MediaController = Ember.Controller.extend(DropletController, {
dropletUrl: 'http://localhost:3000/images',
useArray: true,
actions:{
uploadAllFiles: function() {
var self = this;
$.when(self._super()).then(function(data){
var media = App.Media.find();
// console.log(data);
$.each(data, function(idx, obj) {
media.pushObject(obj);
});
// media.save();
media.reload();
});
}
}
});
在上传完所有文件后调用 uploadAllFiles
并从Rails API返回我的对象(即新创建的模型)。
我必须调用media.reload();
,以便任何操作(即deleteImage)都可以对新添加的对象起作用。