https://jsfiddle.net/n2ne6yLh/10/
所以你需要在文件输入上监听change事件。将每个文件映射到一个新的模型"FileModel"中,然后将其推入observableArray Files中。每个FileModel都包含自己的独立结果、验证函数等。然后布局会处理剩下的事情。var PageModel = function(r) {
var self = this;
this.Files = ko.observableArray();
this.FileErrors = ko.computed(function() {
return _.some(self.Files(), function(file) {
return file.IsValid() === false;
});
});
this.ClearFiles = function() {
document.getElementById("your-files").value = "";
self.Files([]);
};
var control = document.getElementById("your-files");
control.addEventListener("change", function(event) {
// When the control has changed, there are new files
var i = 0,
files = control.files,
len = files.length;
var form = new FormData();
for (; i < len; i++) {
form.append(files[i].name, files[i]);
self.Files.push(new FileModel(files[i], files[i]));
}
}, false);
}
var FileModel = function(r, fileObject) {
var self = this;
this.FileObject = fileObject;
this.Name = r.name;
this.Type = r.type;
this.Size = r.size;
this.IsValidated = ko.observable(false);
this.IsValid = ko.observable();
this.ValidationErrors = ko.observable();
this.ValidateFile = function() {
//Do some ajax to validate file
//console.log('Doing an ajax thing.')
// Randomizers for validation, remove in production
var random_boolean = Math.random() >= 0.5;
var random_strins = Math.random().toString(36).substring(7);
// Set vals based on returned ajax response.
self.IsValidated(true);
self.IsValid(random_boolean);
self.ValidationErrors(random_strins);
};
this.UploadFile = function() {
alert('uploading this file to the interwebs, yay!')
}
}
window.model = new PageModel();
ko.applyBindings(model);
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-push-3">
<div class="form-group">
<div class="input-group">
<input type="file" class="form-control" id="your-files" multiple>
<span class="input-group-btn">
<button class="btn btn-info" data-bind="click: ClearFiles">Clear</button>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-sm-6">
<h4>Validate Files</h4>
<!-- ko if: Files().length > 0 -->
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Size (bytes)</th>
</tr>
</thead>
<tbody>
<!-- ko foreach: Files -->
<tr data-bind="css: IsValid() ? 'success' : ''">
<td><span data-bind="text: Name"></span>
</td>
<td><span data-bind="text: Type"></span>
</td>
<td><span data-bind="text: Size"></span>
</td>
<td>
<button class="btn btn-sm btn-success" data-bind="click: ValidateFile, visible: !IsValidated()">Validate</button>
<button class="btn btn-sm btn-success" data-bind="click: UploadFile, visible: IsValid()">Upload</button>
</td>
</tr>
<!-- /ko -->
</tbody>
</table>
<!-- /ko -->
</div>
<div class="col-sm-6">
<h4>File Errors</h4>
<!-- ko if: FileErrors() -->
<table class="table table-hovered">
<thead>
<tr>
<th>Name</th>
<th>Error Message</th>
</tr>
</thead>
<tbody>
<!-- ko foreach: Files -->
<!-- ko if: IsValid() == false -->
<tr>
<td data-bind="text: Name"></td>
<td data-bind="text: ValidationErrors"></td>
</tr>
<!-- /ko -->
<!-- /ko -->
</tbody>
</table>
<!-- /ko -->
</div>
</div>
</div>
function validateFiles(filesToValidate)) {
foreach(file in filesToValidate)
{
var fileDivWithIdTheNameOfTheFile = @Html.RenderPartial("A_View_WithProgressBar",file)
allFiles.AddElement(fileDivWithIdTheNameOfTheFile );
ajax.Get("YourActionThatReturnsAResultView",file)
.OnSuccess(args)
{
FindDivForCurrentFile.ReplaceWith(args.ResultView)
}
}
}
这种方式大部分代码都在服务器端,只需要一些jQuery代码来替换页面的某些部分,一旦文件验证完成。
我建议使用局部视图。只需创建一个带有所需基本表格布局的局部视图,然后将其用于需要的地方即可。
<div id='partial'/>
success: function(data) {
$('#partial').html(data);
}
插入您的局部视图的HTML