Передача данных из частичного представления в родительское представление - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть страница профиля с функцией поиска по почтовому индексу https://postcodes.io. Пока у меня есть частичное представление с помощью формы Ajax с использованием следующего кода.

@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 голосов
/ 19 февраля 2019

Решение 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% ясно, хотите ли вы, чтобы пользователь имел возможность редактировать поля County и City после просмотра.В приведенном ниже коде они могут.

@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 контроллера.Обратите внимание, что тип Action - 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);
}
0 голосов
/ 19 февраля 2019

Я отвечу на это двумя способами;сначала используя подход, о котором вы изначально спрашивали, а затем, как я предпочел бы реализовать это.

Решение 1

При таком подходе мы скопируем значение 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 может возникнуть искушение вложить элементы формы по причинам компоновки, но вложенные элементы формы недопустимы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...