【问题标题】:An ASP.NET MVC with a view with a dynamic number of inputs具有动态输入数量的视图的 ASP.NET MVC
【发布时间】:2016-11-09 18:50:25
【问题描述】:

好的,这是一个复杂的问题,我对此很陌生,也许我什至不知道如何正确地提问。

我正在使用 ASP.NET MVC 构建应用程序。我有一个视图,其中包含一个表单,该表单具有一个文本框输入,要求用户为他们的遗嘱指定收件人。在输入下方,我想要一个按钮(“添加另一个收件人”),用于向表单添加另一个输入。

这是我使用 Javascript 模拟的方法(单击“是”,然后单击“现金”以查看我在说什么):https://jsfiddle.net/cinerobert/409k27ot/7/

<p>Would you like to leave specific gift in your will?</p>
<p>
  <button onclick="q1AnswerYes()">Yes</button>
  <button onclick="q1AnswerNo()">No</button>
</p>
<br />
<!-- If answer to Q1 is Yes show this block -->
<div id="q1AnswerYesBlock" style="display:none; text-align:center;
margin:auto;">
  <div>What specific gifts would you like to leave?</div>
  <hr>
  <div>
    <button onclick="q2AnswerCash('q2AnswerCashDisp')">Cash</button>
    <button>Car</button>
    <button>Real Estate</button>
    <button>Jewelry</button>
    <button>Other</button>
  </div>
  <div id="q2AnswerCashDisp">
    <!-- Recipient forms get added here -->
  </div>
  <div style="text-align:center;
margin:auto; display:inline">
    <button id="addCashRecipient" style="display:none" onclick="addCashRecipientForm('q2AnswerCashDisp')">Add another recipient</button>
  </div>
</div>

<!-- If answer to Q1 is No show this block -->
<div id="q1AnswerNoBlock" style="display:none">
  <p>Some other crap</p>
</div>
<div id="testFormHTML" style="display:none">
  <form id="testFormId" method="get" style="border-syle:none">
    <fieldset id="fieldsetid" style="border-style:none">
      <div class="formPrompt">
        Amount:
      </div>
      <input type="text">
      <div class="formPrompt">
        Recipient:
      </div>
      <input onblur="submit()" type="text" name="recipient">
      <input style="display:none" class="testFormParamInputId" name="testFormParam" value="">
      <br>
      <br>
    </fieldset>
  </form>
</div>

<script>
var cashRecipientNum = 1;
function q1AnswerYes() {
  document.getElementById("q1AnswerYesBlock").style.display = "block";
  document.getElementById("q1AnswerNoBlock").style.display = "none";
}

function q1AnswerNo() {
  document.getElementById("q1AnswerYesBlock").style.display = "none";
  document.getElementById("q1AnswerNoBlock").style.display = "block";
}

function q2AnswerCash(blockId) {
  if (cashRecipientNum == 1) {
    addForm(blockId, "testForm", cashRecipientNum++);
    document.getElementById("addCashRecipient").style = "display:inline";
  };
}

function addCashRecipientForm(blockId) {
  addForm(blockId, "testForm", cashRecipientNum++);
}

// Function to add a new form with unique action argument to the document.
function addForm(blockId, formArg, numInstance) {
  var formHTML = formArg + "HTML";
  var formId = formArg + "Id";
  var formParamInputId = formArg + "ParamInputId";
  var newFormId = formArg + "Id" + numInstance;
  var div = document.getElementById(formId),
    clone = div.cloneNode(true); // true means clone all childNodes and all eventhandlers
  clone.id = newFormId;
  clone.style = "border-style:none";
  document.getElementById(blockId).appendChild(clone);
  var x = document.getElementById(newFormId).getElementsByClassName(formParamInputId);
  x[0].value = numInstance;

  console.log(x[0].class);
  console.log("here");
}    
</script>

我无法理解的是:

  • 因为我使用的是硬编码的 html 表单(使用标签)而不是 html 助手(如@Html.TextBoxFor),所以每个输入都没有绑定到模型中的任何内容。我可以使用 FormCollection 读取输入,但是当表单提交时,我不知道如何使用用户输入的值重新发布表单。

  • 如果我使用 html 助手 (@Html.TextBoxFor) 并将每个输入绑定到模型中的一个属性,那么我不明白如何允许表单添加无限数量的输入字段

我搜索了动态视图的示例,但我发现的示例与响应模型变化的视图有关。我还没有找到涉及根据用户操作添加无限数量的输入字段的方法。

我知道这是一个毛茸茸的问题,但如果有人能帮助我指出正确的方向,我将非常感激。提前感谢您对新手的耐心。

【问题讨论】:

  • 听起来您需要一个具有List&lt;string&gt; 属性的视图模型。您的&lt;input /&gt; 标记需要的是表单中每个收件人的recipients[n] 名称,从0 开始。MVC 模型绑定器将采用数组索引样式并使用它绑定到模型的recipents 属性(List&lt;string&gt;)。我认为,如果您要发布多个 recipients 输入而没有索引,我认为这也会绑定它
  • 啊,很有趣。你的意思是: ?
  • 我只是做了一个简单的例子,&lt;input name="recipients" /&gt; 或“索引”输入 &lt;input name="recipients[0]" /&gt; &lt;input name="recipients[1]" /&gt; 的输入都可以。您只需要确保在视图模型中使用相同的外壳。您还需要更新视图以使用模型并使用 @Html.InputFor(或 TextBoxFor)填充输入以保留帖子的值
  • 对于动态添加复杂对象的集合项,请参考this answer - 您接受的答案将不起作用,因为您需要生成包含至少2个属性的对象集合(RecipientAmount)
  • 谢谢斯蒂芬。在您链接的示例中,我是否正确地认为 AdminProductDetailModel 将是一个 ArrayList 集合,声明如下: class AdminProductDetailModel : ArrayList { public string fkConfigChoiceCategoryColorId;等}?

标签: javascript asp.net-mvc forms input html-helper


【解决方案1】:

您描述的场景尖叫着视图模型。即使是这样一个简单的方法也会有所帮助

public class WillRecipientsViewModel
{
    public List<string> Recipients { get; set; }
}

那么您的控制器将需要您的表单的相应操作

// Controller
public ActionResult SetWillRecipients()
{
    // Added this to force at least 1 text box into the view
    WillRecipientsViewModel model = new WillRecipientsViewModel
    {
        Recipients = new List<string> { "" };
    };
    return View(model);
}

[HttpPost]
public ActionResult SetWillRecipients(WillRecipientsViewModel model)
{
    // Business logic

    // Go back to the view if an error occurs
    return View(model);
}

// View
@model WillRecipientsViewModel
@using(Html.BeginForm("SetWillRecipients"))
{
    @Html.DisplayFor(model => model.Recipients)
    for (int i = 0; i < Model.Recipients.Count; i++)
    {
        // Generate the textboxes for any values that were previously submitted
        Html.InputFor(model => model.Recipients[i])
    }
}

这会将表单中的值绑定到模型对象,这将使事情变得更容易。然后您只需要确保您的视图使用&lt;input type="text" name="Recipients" /&gt; 来捕获帖子中model 对象中的数据。我还建议您尽最大努力使 input 名称属性与视图模型的大小写紧密匹配,以避免和冲突

更新

我添加了更多代码来举例说明如何将以前的收件人拉入界面

【讨论】:

  • 好的,现在我对其他事情感到困惑。页面上的 javascript 可以更改 @html 元素吗?看起来不像,因为它们在浏览器端呈现为 html。以及相关:如何在发布后保留 javascript 对表单(新表单字段)所做的更改?
  • re:@Html 渲染元素:当页面进入浏览器时,元素已经是标准的 HTML,javascript 与这些标签的交互和修改有 0 个问题。我将在将表单字段放入视图时更新我的​​答案
  • 非常感谢。我欠你。我仍然不太明白 javascript 对页面所做的更改将如何在发布后持续存在。页面不会重新加载吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
相关资源
最近更新 更多