ASP.Net MVC Динамический вход привязан к тому же свойству контроллера - PullRequest
0 голосов
/ 04 декабря 2018

У меня есть 2 поля контроллера, скажем Тип и Данные.В зависимости от значения, выбранного для Типа (Дата или Текст), я хочу, чтобы поле «Данные» динамически отображалось либо как ввод текста, либо как ввод пользовательского таймера.Поскольку в любой момент будет отображаться только один, мне нужно связать с тем же именем свойства (Data).Это то, что я пытаюсь:

@if (Model.Type == "Date")
{
   // custom timepicker control goes here
   <input asp-for="Data" class="form-control timepicker"/>
}
else
{
   <input asp-for="Data" class="form-control text-input" type="text"/>
}

При загрузке страницы отображается только ввод текста, и он отображается / скрывается в зависимости от выбранного типа.Ввод Timepicker никогда не отображается (HTML не создается вообще).

Есть ли способ достичь этого в MVC?

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

ASP MVC уже имеет эту функцию, встроенную в Шаблоны редактирования .Следуя соглашению, вы можете указать шаблон, который будет использоваться для любого типа (включая определяемые пользователем сложные типы), который будет отображаться с помощью @Html.EditorFor().

В двух словах, просто поместите два частичных представления в вашПапка ~/Views/Shared/EditorTemplates, одна с типом модели DateTime, а другая string.Правильный частичный вид будет отображаться при использовании @Html.EditorFor(m => m.Property) в зависимости от типа Property.

Примечание. Редактор по умолчанию для свойства string уже будет входом с type="text", поэтому вам не обязательно указывать этот шаблон .

Смотрите эту ссылку для учебника по шаблонам редактора (и шаблонам отображения): https://exceptionnotfound.net/asp-net-mvc-demystified-display-and-editor-templates/

0 голосов
/ 04 декабря 2018

Вы не можете иметь два элемента <input> с одинаковыми именами.Если опубликовано <form>, содержащее несколько входов с одним и тем же именем, связыватель модели MVC будет привязывать только одно значение из последнего ввода.

Чтобы достичь желаемого, у вас есть два варианта:

  • Либо есть только один вход с name="Data" из type="text" в представлении, и пусть указатель времени записывает время в виде строки для этого ввода.Затем в контроллере проанализируйте это входное значение в зависимости от выбранного Type.

  • Или используйте два входа с name="TextData" и name="TimeData", отключите и скройте один из этих входов.используя JS в зависимости от выбранного Type.В контроллере считайте значение с правого входа в зависимости от выбранного Type.Возможно, это более чистое решение.

В MVC5 второе решение будет выглядеть так (я не знаком с MVC-Core):

@model MyViewModel
@using (Html.BeginForm("Submit", "MyController", FormMethod.Post)) {
    @Html.EditorFor(m => m.Type)
    @Html.EditorFor(m => m.TextData, new { @class = "text-input"})
    @Html.EditorFor(m => m.TimeData, new { @class = "timepicker"})
}

<script type="text/javascript">
    function toggleInput_() {
         if ($('#@Html.IdFor(m => m.Type)').val() === 'Text') {
             $('#@Html.IdFor(m => m.TextData)').prop('disabled', false).show();
             $('#@Html.IdFor(m => m.TimeData)').prop('disabled', true).hide();
         }
         else {
             $('#@Html.IdFor(m => m.TextData)').prop('disabled', true).hide();
             $('#@Html.IdFor(m => m.TimeData)').prop('disabled', false).show();
         }
    }

    $(document).ready(function() {
        $('#@Html.IdFor(m => m.Type)').on('change', function() {
            toggleInput_(); // toggle when drop down changes
        });

        toggleInput_(); // toggle initially on page load
    });
</script>

Контроллер:

[HttPost]
public ActionResult Submit(MyViewModel postData) {

    string textValue = null;
    DateTime? timeValue = null;

    if (postData.Type == "Text") {
        textValue = postData.TextData;
    }
    else {
        timeValue = postData.TimeData;
    }

    // ...
}
...