【问题标题】:asp.net core nested formsasp.net 核心嵌套表单
【发布时间】:2017-05-09 05:11:52
【问题描述】:

我有 3 个模型 - 学校、教室和课程。

一所学校可以有很多教室,一个教室可以教授很多课程。

public class School
{
    public int SchoolId { get; set; }
    public string SchoolName { get; set; }
    public List<Classroom> Classrooms { get; set; }
}

public class Classroom
{
    public int ClassroomId { get; set; }
    public string Room { get; set; }
    public List<Course> Courses { get; set; }
    public virtual int SchoolId { get; set; }
}

public class Course
{
    public int CourseId { get; set; }
    public string CourseName { get; set; }
    public virtual int ClassroomId { get; set; }
}

我想为学校创建 CRUD 操作,我可以在其中将 0 添加到多个教室,并在每个教室中以一种形式创建 0 到多个课程。允许用户在创建学校的过程中动态添加教室和这些教室中的课程

我现在完成这项工作的方式是硬编码(其中 School 是 @Model):

<div class="col-md-10">
    <input asp-for="@Model.SchoolName" class="form-control" />
</div>
<div class="col-md-10">
    <input asp-for="@Model.Classroom[0].Room" class="form-control" />
</div>
<div class="col-md-10">
    <input asp-for="@Model.Classroom[0].Course[0].CourseName" class="form-control" />
</div>
<div class="col-md-10">
    <input asp-for="@Model.Classroom[0].Course[1].CourseName" class="form-control" />
</div>
<div class="col-md-10">
    <input asp-for="@Model.Classroom[0].Course[3].CourseName" class="form-control" />
</div>

我希望用户能够添加更多教室和更多课程,或者能够在表单上动态删除它们。

【问题讨论】:

  • 不应该反过来吗?学校不应该有“课程”而不是教室吗?课程是否必须附有教室效果?此外,如果您使用实体框架 - 它会自动创建一个具有多对多关系的新表。 - 顺便说一句,它不称为“零对多”,而是称为“一对多”
  • 当我说从零到多时,我指的不是数据库关系,而是 List Courses & List 教室,它们可以包含 0 到多个项目。我正在寻求有关嵌套表单的帮助,因此是 MVC 模式的视图部分。

标签: c# asp.net model-view-controller nested-forms


【解决方案1】:

您可以使用局部视图和 JQuery 在 html 表中创建动态行。

我有一个至少需要一个行项目的资产转移表单。我放置了一个资产选择列表和一个按钮,用于通过部分视图将资产及其详细信息(行项目)添加到 html 表中。

局部视图

@model ITFixedAssets.Models.TransferLineItem


@{//this helps with naming the controls within the main view/page
    Models.TransferLineItem TransferLineItem = new Models.TransferLineItem();
   }


<tr>
    <td>
        <a href="#"><span class="glyphicon glyphicon-trash" style="padding-right:5px;"  data-action="removeItem" onclick="RemoveRow(this);"></span></a>
    </td>
    <td>
        <label asp-for="@TransferLineItem.Id" class="form-control" id="row" style="height:34px;margin-top:5px;"></label>
    </td>
    <td>
        <input  asp-for="@TransferLineItem.Asset" class="form-control" />
    </td>
    <td>
        <select asp-for="@TransferLineItem.Condition" class="form-control">
            <option>Please Select</option>
            <option value="New">New</option>
            <option value="Good">Good</option>
            <option value="Bad">Bad</option>
        </select>
        <span asp-validation-for="@TransferLineItem.Condition" class="text-danger"></span>
    </td>
    <td>
        <input asp-for="@TransferLineItem.AssetDescription1" class="form-control" value="@ViewBag.AssetDescription1" />
    </td>
    <td>
        <input asp-for="@TransferLineItem.AssetDescription2" class="form-control" />
    </td>
    <td>
        <input asp-for="@TransferLineItem.InventoryNum" class="form-control" />
    </td>
    <td>
        <input asp-for="@TransferLineItem.SerialNumber" class="form-control" />
    </td>
</tr>

当点击“添加资产”按钮时,它会调用一个 JS 函数,该函数使用 ajax GET 来运行一个返回部分视图的“代码隐藏”函数,该部分视图基本上是要放置到html 表格。

返回局部视图的 JS 函数和“代码隐藏”函数。

function AddRow() {
        $.ajax({
            type: "GET",
            url: "Create?handler=AddLineItemRow"
        }).success(function (data) {
           AddNewRow(data);
        });
}
     public PartialViewResult OnGetAddLineItemRow()
    {
        PartialViewResult partialViewResult = new PartialViewResult();

        partialViewResult.ViewName = "_LineItem";

        return partialViewResult;

    }

如果成功,则将部分视图(“数据”)传递给另一个 JS 函数,该函数将行添加到表中,并将控件的通用 ID 和名称更改为表单时所需的适当“数组”样式提交是为了将行项目保存到数据库中。

//appends the transfer line item table with a new row (partial view)
function AddNewRow(data)
{
    //******************************************************
    //*************add the new to the table**********************
    //append the table with the new row
    $('#LineItems').append(data);
    //******************************************************


    //get value of asset drop down
    var asset = $("#assetList").val();


    //******************************************************
    //*****add the row number to the id values of the controls********

    //get the length of the table for new row # 
    //(subtract 1, not sure why unless it's adding the headers into the count)
    var rowNum = $("#LineItems tr").length - 1;

    //build new name to add to the controls
    var nameIndex = rowNum - 1;
    var newName = "[" + nameIndex + "].";

    //get the row label
    var lblRow = $("#row");

    //create new id for the row label
    var newId = "row_" + rowNum;

    //apply new id
    lblRow.attr("id", newId);

    //get the last row in the table
    var lastRow = $("#LineItems").find("tr").last();

    ////format id values for the input controls
    //and add names for the controls 
    lastRow.find("input").each(function () {

        // get id of this input control
        var ctrl = $(this).attr("id");

        //concatenate the row number to the id
        var newId = ctrl + "_" + rowNum;

        //assign new id to control
        $(this).attr("id", newId);

        //add the index to the control'
        $(this).attr("name",$(this).attr("name").replace(".", newName));
        

    });

    //update the select list (for condition) id value
    var selectControl = lastRow.find("select");

    //get id of the select control
    var scId = selectControl.attr("id");

    //concatenate the row number to the id
    newId = scId + "_" + rowNum;

    //assign new id to control
    selectControl.attr("id", newId);

    //add new name to control
    selectControl.attr("name", selectControl.attr("name").replace(".", newName));

    //this ajax calls the function 'OnGetPopulateLineItemRow' in the code behind
    //and passes the asset # and row # as parameters.  the success function 
    //receives the return value from the OnGetPopulateItemRow function and 
    //passes that 'data' to the PopulateRow function below
    $.ajax({
        type: "GET",
        url: "Create?handler=PopulateLineItemRow",
        data: { _asset: asset },
        //data: { _asset: asset, row: rowNum }
        dataType: 'json',
        success: function (data) {
            PopulateRow(asset, data, rowNum);
        }
    });

}

在将新行添加到表中并更改名称和 id 后,另一个 ajax 'GET' 用于调用 'code behind' 函数以获取新行中控件的值(如可以在上面的sn-p中看到)。

获取资产项目详细信息的函数

 public JsonResult OnGetPopulateLineItemRow(string _asset)
    {

        //stores named value pairs for the result
        Dictionary<string, string> results = new Dictionary<string, string>();

        //get record from the database for the specified asset (_asset)
        var asset = from a in _context.Asset select a;
        asset = asset.Where(a => a.Asset1 == _asset); 

        //get value for each field
        var description1 = from d in asset select d.AssetDescription;
        var description2 = from d in asset select d.AssetDescription2;
        var inventoryNum = from d in asset select d.InventoryNo;
        var serialNum = from s in asset select s.SerialNo;

        //add the name value pairs to the collection
        results.Add("description1", description1.ToList()[0].ToString());
        results.Add("description2", description2.ToList()[0].ToString());
        results.Add("inventoryNum", inventoryNum.ToList()[0].ToString());
        results.Add("serialNum", serialNum.ToList()[0].ToString());


        return new JsonResult(results);

    }

最后将这些结果传回成功函数,并使用 JQuery 填充值

function PopulateRow(asset, data,rowNum) {

    $("#row" + "_" + rowNum).text($("#LineItems tr").length - 1);
    $("#TransferLineItem_Asset" + "_" + rowNum).val(asset);
    $("#TransferLineItem_AssetDescription1" + "_" + rowNum).val(data["description1"]);
    $("#TransferLineItem_AssetDescription2" + "_" + rowNum).val(data["description2"]);
    $("#TransferLineItem_InventoryNum" + "_" + rowNum).val(data["inventoryNum"]);
    $("#TransferLineItem_SerialNumber" + "_" + rowNum).val(data["serialNum"]);

    //reset drop down
    $('#assetList').prop('selectedIndex', 0);
}

作为旁注。直到最近我还在使用 ASP.net 网络表单。我仍在尝试了解如何使用服务器端编码来完成我认为简单的事情,对我来说,使用 MVC 和 Razor 似乎更复杂。

【讨论】:

  • 虽然这可能会回答(一年前的)问题,但您可以使用更多文本、代码片段和文档来扩展您的答案。请编辑您的问题:)
猜你喜欢
  • 1970-01-01
  • 2021-12-18
  • 2021-12-01
  • 2019-04-13
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
  • 2012-02-18
  • 2017-10-23
相关资源
最近更新 更多