Данные таблицы HTML не обновляются в модели

0

У меня есть ViewModel, который содержит два списка Условий - BuyConditions и SellConditions - плюс несколько атрибутов - Name и т.д. Списки отображаются с использованием таблиц в представлении. jQuery позволяет манипулировать таблицами - добавление условий в таблицы (из условия покупки/продажи условий DDL) и удаление условий из таблиц.

Моя проблема в том, что списки условий не обновляются в модели, когда они отправляются обратно на контроллер.

Что-то, что может указывать на проблему, заключается в том, что когда модель возвращается в представление (из-за ModelStat.IsValid), данные в DDL Markets все еще существуют, но данные в DDL условия покупки и продажи не имеют.

Я не могу найти пример в сети, чтобы выяснить, где я ошибаюсь. Кто-нибудь сделал это раньше?

ViewModel:

public class StrategyViewModel
{
    public string ID { get; set; }

    [Display(Name = "Strategy Name")]
    public string StrategyName { get; set; }

    [Display(Name = "Market")]
    public string SelectedMarketID { get; set; }

    [Display(Name = "Asset Type")]
    public string SelectedShareTypeID { get; set; }

    [Display(Name = "Share")]
    public string SelectedShareID { get; set; }

    public bool Active { get; set; }

    public IEnumerable<Market> Markets { get; set; }              // top level of three cascading DDL - the other two populated via JQuery
    public IEnumerable<Condition> BuyConditionList { get; set; }  // used to populate DDL
    public IEnumerable<Condition> SellConditionList { get; set; } // used to populate DDL 
    public List<BuyCondition> BuyConditions { get; set; }         // list of Buy Conditions
    public List<SellCondition> SellConditions { get; set; }       // list of Sell Conditions

    AppRepository repository = new AppRepository();

    public StrategyViewModel()
    {
        // populate lists
        Markets = ListUtils.AddDefaultOptionToMarketList( repository.GetMarkets(), -1, "Select a Market" ).AsEnumerable();
        BuyConditionList = repository.GetConditions();
        SellConditionList = repository.GetConditions();
        BuyConditions = new List<BuyCondition>();
        SellConditions = new List<SellCondition>();
    }
}

контроллер:

 public ActionResult Create()
    {
        StrategyViewModel model = new StrategyViewModel();

        return View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "User, Admin")]
    public ActionResult Create(StrategyViewModel model)
    {

        // for debugging
        var errorList = ModelState.Values.SelectMany(v => v.Errors);

        if (ModelState.IsValid)
        {

            var user = repository.GetCurrentUser(User.Identity.GetUserId());
            var strategy = new Strategy();

            strategy.StrategyName = model.StrategyName;
            strategy.ShareID = Convert.ToInt32(model.SelectedShareID);
            strategy.BuyConditions = model.BuyConditions.ToList();
            strategy.SellConditions = model.SellConditions.ToList();
            strategy.Active = model.Active;

            int strategyID = repository.AddStrategy(user, strategy);

            return RedirectToAction("Index");

        }

        return View(model);
    }

Посмотреть:

@model ShareTrigger.Models.StrategyViewModel

@{
ViewBag.Title = "Create";
}

@{Html.EnableUnobtrusiveJavaScript(true);}


<script type="text/javascript">
$(document).ready(function () {

    $(function () {
        $('#SelectedMarketID').change(function () {
            var selectedMarketID = $(this).val();
            $.getJSON('@Url.Action("ShareTypes")', { marketId: selectedMarketID }, function (shareTypes) {

                var shareTypesSelect = $('#SelectedShareTypeID');

                shareTypesSelect.empty();

                $.each(shareTypes, function (index, shareType) {
                    shareTypesSelect.append($('<option/>').attr('value', shareType.Value).text(shareType.Text));
                });

                $('#SelectedShareTypeID').trigger("change");

            });
        });

        $('#SelectedShareTypeID').change(function () {
            var selectedShareTypeId = $(this).val();
            var selectedMarketID = $('#SelectedMarketID').val();

            $.getJSON('@Url.Action("Shares")', { shareTypeId: selectedShareTypeId, marketID: selectedMarketID }, function (shares) {

                var sharesSelect = $('#SelectedShareID');

                sharesSelect.empty();

                $.each(shares, function (index, share) {
                    sharesSelect.append($('<option/>').attr('value', share.Value).text(share.Text));
                });
            });
        });
    });

    $('#AddBuyCondition').click(function () {

        var conditionID = +$("#BuyConditionList").val();
        if (conditionID != -2) {
            conditionID = +$("#BuyConditionList").val();
            var conditionText = $("#BuyConditionList").find('option:selected').text();

            $("tr:contains('Add')").remove();

            $('#BCDropDownRow').before('<tr class="bcrow"><td class="BuyConditionCell" data-conditionID="' + conditionID + '"><input data-val="true" data-val-number="The field ConditionID must be a number." data-val-required="The ConditionID field is required." id="item_ConditionID" name="item.ConditionID" type="hidden" value="' + conditionID + '">' + conditionText + '</td><td><button class="RemoveBuyCondition type="button" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-minus"></span></button></td></tr>');
            $("#BuyConditionList").find('option:selected').remove();
            var rows = $('#BuyConditionList option').size();
            if (rows == 0) { $("#BuyConditionList").append('<option value="-2">No more conditions to select</option>'); }
        }
    });

    $('#BuyConditionsTable').on('click', '.RemoveBuyCondition', function () {
        var conditionID = +$(this).parent().parent().find('.BuyConditionCell').data('conditionid');
        var conditionText = $(this).parent().parent().find('.BuyConditionCell').text();

        $(this).closest('.bcrow').remove();

        $('#BuyConditionList option[value="-2"]').remove();

        $("#BuyConditionList").append('<option value="' + conditionID + '">' + conditionText + '</option>');

        var options = $('#BuyConditionList option');
        var arr = options.map(function (_, o) { return { t: $(o).text(), v: o.value }; }).get();
        arr.sort(function (o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; });
        options.each(function (i, o) {
            o.value = arr[i].v;
            $(o).text(arr[i].t);
        });
    });


    $('#AddSellCondition').click(function () {

        var conditionID = +$("#SellConditionList").val();
        if (conditionID != -2) {
            conditionID = +$("#SellConditionList").val();
            var conditionText = $("#SellConditionList").find('option:selected').text();

            $("tr:contains('Add')").remove();
            $('#SCDropDownRow').before('<tr class="scrow"><td class="SellConditionCell" data-conditionID="' + conditionID + '"><input id="item_ConditionID" name="item.ConditionID" type="hidden" value="' + conditionID + '">' + conditionText + '</td><td><button class="RemoveSellCondition type="button" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-minus"></span></button></td></tr>');
            $("#SellConditionList").find('option:selected').remove();
            var rows = $('#SellConditionList option').size();
            if (rows == 0) { $("#SellConditionList").append('<option value="-2">No more conditions to select</option>'); }
        }
    });

    $('#SellConditionsTable').on('click', '.RemoveSellCondition', function () {
        var conditionID = +$(this).parent().parent().find('.SellConditionCell').data('conditionid');
        var conditionText = $(this).parent().parent().find('.SellConditionCell').text();

        $(this).closest('.scrow').remove();

        $('#SellConditionList option[value="-2"]').remove();

        $("#SellConditionList").append('<option value="' + conditionID + '">' + conditionText + '</option>');

        var options = $('#SellConditionList option');
        var arr = options.map(function (_, o) { return { t: $(o).text(), v: o.value }; }).get();
        arr.sort(function (o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; });
        options.each(function (i, o) {
            o.value = arr[i].v;
            $(o).text(arr[i].t);
        });
    });
});
</script>

<h2>Create Strategy</h2>

@using (Html.BeginForm())
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <hr />
    @Html.ValidationSummary(true)

    <div class="form-group">
        @Html.LabelFor(model => model.StrategyName, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.StrategyName)
            @Html.ValidationMessageFor(model => model.StrategyName)
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.SelectedMarketID, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(x => x.SelectedMarketID, new SelectList(Model.Markets, "MarketId", "MarketCode"))
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.SelectedShareTypeID, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(x => x.SelectedShareTypeID, Enumerable.Empty<SelectListItem>(), "Select an Asset Type")
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.SelectedMarketID, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(x => x.SelectedShareID, Enumerable.Empty<SelectListItem>(), "Select a Share")
        </div>
    </div>

    <div>
        &nbsp;
    </div>

    <div class="col-md-10">
        <table class="table" id="BuyConditionsTable">
            <tr>
                <th>
                    @Html.DisplayName("Buy Conditions")
                </th>
                <th></th>
            </tr>

            @foreach (var item in Model.BuyConditions)
            {
                <tr>
                    <td>
                        @Html.HiddenFor(modelItem => item.ConditionID)
                        @Html.DisplayFor(modelItem => item.ConditionName)
                    </td>
                    <td></td>
                </tr>
            }
            <tr id="BCDropDownRow">
                <td>
                    <button id="AddBuyCondition" type="button" class="btn btn-default btn-xs">
                        <span class="glyphicon glyphicon-plus"></span>
                    </button>
                    &nbsp;
                    @Html.DropDownListFor(x => x.BuyConditionList, new SelectList(Model.BuyConditionList, "ConditionID", "ConditionName"))
                </td>
                <td></td>
            </tr>
        </table>
    </div>

    <div>
        &nbsp;
    </div>

    <div class="col-md-10">
        <table class="table" id="SellConditionsTable">
            <tr>
                <th>
                    @Html.DisplayName("Sell Conditions")
                </th>
                <th></th>
            </tr>

            @foreach (var item in Model.SellConditions)
            {
                <tr>
                    <td>
                        @Html.HiddenFor(modelItem => item.ConditionID)
                        @Html.DisplayFor(modelItem => item.ConditionName)
                    </td>
                    <td></td>
                </tr>
            }
            <tr id="SCDropDownRow">
                <td>
                    <button id="AddSellCondition" type="button" class="btn btn-default btn-xs">
                        <span class="glyphicon glyphicon-plus"></span>
                    </button> &nbsp;
                    @Html.DropDownListFor(x => x.SellConditionList, new SelectList(Model.SellConditionList, "ConditionID", "ConditionName"))
                </td>
                <td></td>
            </tr>
        </table>
    </div>

    <div class="form-group">
        <div class="col-md-offset-9 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

@section Scripts {
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
}
  • 0
    когда вы говорите «Списки условий не обновляются», означает ли это BuyConditionList или BuyConditions ?
  • 0
    Извините - я имею в виду, что списки BuyConditions и SellConditions не обновляются. Я пытаюсь создать список BuyConditions и список SellConditions, которые связаны со Стратегией. Эти списки создаются путем выбора из DropDownLists, которые заполняются данными BuyConditionList и SellConditionList.
Показать ещё 1 комментарий
Теги:
razor
asp.net-mvc
html-helper

1 ответ

1
Лучший ответ

Причина, по которой вы получаете BuyConditions и SellConditions пустым из-за следующего кода

@Html.HiddenFor(modelItem => item.ConditionID)

Это отобразит ВСЕ как

<input type="hidden" id="item_ConditionID" name="item.ConditionID" />

Он не может быть разрешен в действии контроллера Create из-за неправильного наименования.

Вместо этого он должен был

@Html.HiddenFor(x => x.SellConditions[index].ConditionID)

Это даст управление как (если index равен 0)

<input type="hidden" id="SellConditions_0__ConditionID" name="SellConditions[0].ConditionID" />

Следовательно, блок foreach должен быть следующим

@foreach (int index = 0; index < Model.SellConditions.Count; index++)
   {
        <tr>
            <td>
                @Html.HiddenFor(x => x.SellConditions[index].ConditionID)
                @Html.DisplayFor(x => x.SellConditions[index].ConditionName)
            </td>
            <td></td>
        </tr>
   }

И то же правило для BuyConditions тоже.

  • 0
    Да, 100%. Спасибо, любезно. Ргдс, Дэйв. Небольшое наблюдение: блок foreach становится блоком for .
  • 0
    Ой, извините. Спасибо за это :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню