根据控制器响应动态更改视图部分

7
我正在寻求以下情况的最佳建议:
  • 用户可以选择一个或多个CSV文件进行验证(附件1),点击"验证"按钮后,该文件经过验证代码(显示进度条,直到返回输出)。
  • 返回响应是每个选择要验证的文件的成功消息或错误详细信息(附件2)。
  • 成功验证的文件现在可以通过"上传"按钮上传到Azure存储。

附件1 enter image description here

附件2 enter image description here

现在,为了使一切都变得“异步”,我的想法是视图需要为每个文件具有单独的灵活部分。

我正在使用MVC5剃须器视图和knockout.js,我对部分视图有一个不错的想法,但我不确定如何处理。如果不是部分视图,那么什么是最佳方法。


你有检查过这个链接吗:https://dev59.com/7GAf5IYBdhLWcg3wizEE - Saravanan
这确实有所帮助,但我的主要关注点是如何在保持相同的模型和控制器的情况下为每个文件实现UI、显示/隐藏按钮和消息。 - Sajal
您可以有一个通用的视图页面,显示文件名,如果正在上传,则显示剩余时间,否则显示上传按钮或验证消息。使用单个部分视图并从控制器填充值。 - Saravanan
再次,如何实现这个?我怎么知道用户选择了哪个文件进行验证?我该如何仅更新此文件的模型,同时保持其他文件的模型不变。 - Sajal
@user3297291,我不是要求代码,而是要求书面说明如何构建HTML,以便一个文件的处理不会受到影响或影响其他文件的处理阶段。 - Sajal
显示剩余4条评论
3个回答

4
我的想法是视图需要为每个文件拥有独立的灵活部分。 我认为你需要一个单独的模型/类来运行ajax命令,至少这是我理解你的解释的方式。 看看这个jsfiddle,我已经添加了一些随机的true/false和字符串内容,以尽快模拟您的布局。测试时请尝试使用5个或更多的文件(JS中的随机生成器有点棘手)。

https://jsfiddle.net/n2ne6yLh/10/

所以你需要在文件输入上监听change事件。将每个文件映射到一个新的模型"FileModel"中,然后将其推入observableArray Files中。每个FileModel都包含自己的独立结果、验证函数等。然后布局会处理剩下的事情。
您需要查看FormData Web API以便在JavaScript中对文件进行操作。如果您的客户/用户使用过时的浏览器,则可以使用FormData的shims/polyfills、jquery等工具。 https://developer.mozilla.org/en-US/docs/Web/API/FormData

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>


谢谢你!这个确实达到了我的预期,尽管我正在寻找使用部分视图的纯razor方法。我更喜欢Angular js。如果在razor中没有出现什么问题,我会接受这个作为最终答案。非常感谢。 - Sajal

2
以下是一个简单的算法,假设您的HTML中有一个id为“allFiles”的
标签。
你可以在你的主视图文件里写下以下代码:
 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代码来替换页面的某些部分,一旦文件验证完成。


1

我建议使用局部视图。只需创建一个带有所需基本表格布局的局部视图,然后将其用于需要的地方即可。

<div id='partial'/>

在您隐藏的主表单中。使用 knockout 或 jquery 将文件发布到您的上传操作。让操作返回您的部分视图。然后使用 knockout 或 jquery 的成功回调,执行类似于以下内容的操作:
success: function(data) {
             $('#partial').html(data);
          }

插入您的局部视图的HTML


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接