将数据从部分视图传递到父视图

时间:2019-02-13 17:20:17

标签: c# ajax asp.net-mvc

我有一个个人资料页面,该页面具有https://postcodes.io中的邮政编码查找功能。到目前为止,我已经使用下面的代码使用Ajax Form创建了Partial View。

@using (Ajax.BeginForm("_CityLookUp", "Home", new AjaxOptions
{
    HttpMethod = "POST",
    UpdateTargetId = "div1",
    InsertionMode = InsertionMode.Replace
}))
{
    <div id="div1">
        <div class="form-group">
            @Html.LabelFor(m => m.PostCode, new { @class = "col-md-2 control-label" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.PostCode, new { @class = "form-control" })
            </div>
        </div>
        <div class="form-group">
                <div class="col-md-10">
                    @Html.HiddenFor(m => m.County, new { @class = "form-control", id = "County" })
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-10">
                    @Html.HiddenFor(m => m.City, new { @class = "form-control", id = "City" })
                </div>
            </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" class="btn btn-primary" value="Look Up" />
            </div>
        </div>
    </div>
}

这有效。然后,我使用主配置文件表单在主配置文件页面上渲染了部分页面。

我只想将其他两个隐藏字段中的值分配给主页中的字段。

部分控制器

    [HttpGet]
    public PartialViewResult _CityLookUp()
    {
        return PartialView();
    }

    [HttpPost]
    public PartialViewResult _CityLookUp(string postcode)
    {
        var client = new PostcodesIOClient();
        var result = client.Lookup(postcode);
        var jst = new AddressLookupViewModel();
        jst.City = result.AdminDistrict;
        jst.County = result.AdminCounty;
        jst.PostCode = postcode;
        ViewBag.City = jst.City;
        ViewBag.County = jst.County;

        var results = new BooksViewModel();
        results.City = jst.City;
        results.County = jst.County;

        return PartialView(jst);
    }

我尝试了一个新的视图模型,并将结果分配给该视图模型,但这没有用。尝试使用JavaScript来获取隐藏字段的值,没有运气。如果您希望使用单独的方法,请说明如何实现该方法。

父视图

@model TestingView.Models.ParentViewModel
<div class="container">

    @Html.Partial("_CityLookUp")

    <div class="form-group">
        <div class="col-md-10">
            @Html.TextBoxFor(v => v.City, new { @class = "form-control", id = "City" })
        </div>
    </div>
</div> 

PartialViewModel

namespace TestingView.Models
{
    public class AddressLookupViewModel
    {
        public string PostCode { get; set; }
        public string County { get; set; }
        public string City { get; set; }

    }
}

父视图模型

namespace TestingView.Models
{
    public class ParentViewModel
    {
        public string City { get; set; }
        public string County { get; set; }
    }
}

侧面问题:由于某些原因,当我将鼠标悬停在

上时
@Html.HiddenFor(m => m.City, new { @class = "form-control", id = "City" })

在父视图上,它在父视图中引用了AddressLookUpViewModel而不是BooksViewModel。我已经添加了两个视图模型。

2 个答案:

答案 0 :(得分:1)

我将通过两种方式回答:首先使用您最初询问的方法,然后我将如何实现它。

解决方案1 ​​

通过这种方法,我们会将City元素的值从局部视图复制到父视图。

我们需要解决的第一件事是,当您现在查看个人资料时,将有两个元素的ID为“ City”;一个来自父页面,另一个来自部分页面。这是无效的标记,它将对任何潜在的解决方案造成问题。

在父视图中重命名ID属性:

@Html.TextBoxFor(v => v.City, new { @class = "form-control", id = "Profile_City" })

更新部分视图以成功获取一组邮政编码值时调用js函数:

@using (Ajax.BeginForm("_CityLookUp", "Home", new AjaxOptions
{
    HttpMethod = "POST",
    UpdateTargetId = "div1",
    InsertionMode = InsertionMode.Replace,
    OnSuccess = "UpdateProfile" // Add this
}))

在父视图的末尾添加一个js函数UpdateProfile:

@section scripts {
    <script>
        function UpdateProfile()
        {
            var City = $("#City").val();
            alert(City);
            $("#Profile_City").val(City);
        }
    </script>
    }

这应该是所需要的。警报就在那里进行调试。

@section scripts代码将被插入到您的_Layout.cshtml,在其中它调用@RenderSection("scripts", required: false),这是默认MVC项目的一部分。

一个可能会出现的问题是,当将父视图构建到form中时,由于布局原因,您可能会想将表单元素嵌套,但是不允许嵌套表单元素。

答案 1 :(得分:1)

解决方案2

此方法使用jQuery's ajax()方法来获取数据并直接在表单上填充相关字段。

设置模型。

namespace TestingView.Models
{
    public class ProfileViewModel
    {
        public string PostCode { get; set; }
        public string County { get; set; }
        public string City { get; set; }
    }
}

这是AddressLookupViewModel的副本,因为它包含所有必填字段。我只是对其进行了重命名,以表明它用于主要个人资料表单本身。

创建视图。

该视图现在只有一个Html.BeingForm(),并且“查找”按钮绑定到ajax函数,而不是提交ajax表单。

我是否100%不清楚您是否希望用户在查找后能够编辑“县”和“城市”字段。在下面的代码中,他们可以。

@model TestingView.Models.ProfileViewModel
@using (Html.BeginForm())
{
    <div class="form-group">
        @Html.LabelFor(m => m.PostCode, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.PostCode, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <button type="button" class="btn btn-primary" onclick="Lookup()">Look Up</button>
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.County, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.County, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.City, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.City, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-primary" value="Submit" />
        </div>
    </div>
}

@section scripts {
    <script>
        function Lookup() {
            $.ajax("/Home/CityLookup", {
                type: "POST",
                dataType: 'json',
                data: {
                    postcode: $("#PostCode").val()
                }
            })
            .success(function (response) {
                console.log("Success");
                console.log(response);
                var cityObj = response;
                $("#City").val(cityObj.City);
                console.log("City " + cityObj.City);
                $("#County").val(cityObj.County);
            })
            .error(function () {
                alert("There was a problem looking up the postcode");
            })
        };
    </script>
    }

创建一个控制器来服务ajax请求。这很大程度上取决于您的POST _CityLookUp控制器。请注意,操作类型为JsonResult,返回值将jst对象转换为JSON字符串。使用JSON使查找可扩展;我们可以将多个属性作为一个对象返回,并将其解压缩到javascript对象中以供客户端使用。

[HttpPost]
public JsonResult CityLookup(string postcode)
{
    var client = new PostcodesIOClient();
    var result = client.Lookup(postcode);
    var jst = new AddressLookupViewModel();
    jst.City = result.AdminDistrict;
    jst.County = result.AdminCounty;
    jst.PostCode = postcode;
    return Json(jst);
}