Каскадные поля со списком Telerik запоминают выбранное значение после привязки данных на стороне клиента - PullRequest
1 голос
/ 11 января 2012

У меня есть два поля со списком и сетка в моем MVC View:

<div id="Products" class="products maintField">
    @Html.Label("something", "Product:")
    @(Html.Telerik().ComboBox().Name("productList")
                               .AutoFill(true)
                               .DataBinding(c => c.Ajax().Select("GetProducts", "Maintenance").Enabled(true).Cache(true))
                               .Filterable(c => c.FilterMode(AutoCompleteFilterMode.StartsWith).Enabled(true))
                               .HighlightFirstMatch(true)
                               .ClientEvents(eb =>
                               {
                                   eb.OnChange("productChanged");
                               })
    )
</div>
<div id="Layouts" class="layout maintField">
    @Html.Label("something", "Layout:")
    @(Html.Telerik().ComboBox().Name("layoutList")
                               .ClientEvents(eb =>
                               {
                                   eb.OnChange("layoutChanged");
                               })
    )
</div>
<div style="clear: both;"/>
<div class="fields">
    @(Html.Telerik().Grid<MaintenanceModel>().Name("fieldList")
        .DataBinding(bc =>
        {
            bc.Ajax().Select("GetProductFields", "Maintenance", new { prodID = 0, layoutID = 0 }).Enabled(true);
        })
        .ClientEvents(c =>
        {
            c.OnDataBound("fieldGridBound");  
        })
        .Columns(c =>
        {
            c.Bound(mm => mm.Field_ID).ClientTemplate("<input id='Field_ID_<#= Field_ID #>' type='checkbox' name='checkedRecords' class=\"checkBoxGroup\" value='<#= Field_ID #>' />")
                                      .Title("<input id='mastercheckbox' type='checkbox' style='display:none;' />")
                                      .HeaderHtmlAttributes(new { style = "text-align: center;" })
                                      .Width(36)
                                      .HtmlAttributes(new { style = "text-align:center" });
            c.Bound(fld => fld.Field_Name).Title("Field Name").Width(225);
            c.Bound(fld => fld.Field_Description).Title("Field Description");
        }).Scrollable(c =>
        {
            c.Enabled(true);
            c.Height(700);
        }).Footer(false).Sortable(c =>
        {
            c.Enabled(false);
            c.OrderBy(oc =>
            {
                oc.Add(fld => fld.SeqNbr);
            });
        })
    )
</div>

А с некоторыми менее красивыми JS каскадные списки и в конечном итоге заполняют сетку:

function productChanged(e) {
    clearLayout();
    var layoutCombo = $("#layoutList").data('tComboBox');

    if (layoutCombo == null) {
        alert("Can't find layoutList");
        return;
    }

    if (e.value == "" || e.value == null) {
        clearLayout();
        return;
    }

    layoutCombo.loader.showBusy();
    $.get('@Url.Action("GetProductLayouts", "Maintenance")', { prodID: e.value }, function (result) {
        layoutCombo.dataBind(result);
        layoutCombo.loader.hideBusy();
    });
}
function layoutChanged(e) {
    var prodCombo = $("#productList").data('tComboBox');
    var fieldGrid = $("#fieldList").data('tGrid');

    if (fieldGrid == null) {
        alert("Can't find fieldList");
    }
    if (prodCombo == null) {
        alert("Can't find prodCombo");
    }

    if (e.value == "" || e.value == null) {
        clearGrid();
        return;
    }

    fieldGrid.rebind({ prodID: prodCombo.value(), layoutID: e.value });
    $("#mastercheckbox").css("display", "block");
}
function fieldGridBound(e) {
    var prodCombo = $("#productList").data('tComboBox');
    var layoutCombo = $("#layoutList").data('tComboBox');

    $.get('@Url.Action("GetLayoutFields", "Maintenance")', { prodID: prodCombo.value(), layoutID: layoutCombo.value() }, function (result) {
        var cbGroup = $(".checkBoxGroup");

        $(cbGroup).each(function (i, e) {
            if (result.indexOf(e.value) >= 0) {
                $(e).attr('checked', 'checked');
            } else {
                $(e).removeAttr('checked');
            }
        });
    });
}

Это прекрасно работает, за исключением ситуации, когда два поля со списком заполнены, сетка привязана, и пользователь выбирает другое значение из первого поля со списком. Второе поле со списком перепривязывается, как и ожидалось, но если значения, связанные с полем со списком, не изменились (в позиции или в отображаемом значении) и пользователь снова выбирает тот же элемент, событие изменения не запускается.

Конкретный пример

В базе данных у меня есть иерархия продуктов и макетов:

 Product A
     Platinum Layout
     Gold Layout
     Silver Layout
 Product B
     Platinum Layout
     Gold Layout
     Silver Layout
 Product C
     Platinum Layout
     Silver Layout

Сценарий 1

  1. Пользователь выбирает «Продукт A» из первого выпадающего списка, в результате чего второй выпадающий список заполняется макетами Platinum, Gold и Silver.
  2. Пользователь выбирает «Платиновый макет» из второго выпадающего меню, в результате чего соответствующая информация отображается в сетке.
  3. Пользователь выбирает «Продукт B» из первого выпадающего списка, в результате чего второй выпадающий список снова заполняется макетами Platinum, Gold и Silver.
  4. Пользователь снова выбирает 'Platinum Layout' из второго выпадающего меню, однако измененное событие не срабатывает, потому что поле со списком не забывало то, из чего было выбрано, до того, как было выполнено восстановление.

Сценарий 2

  1. Пользователь выбирает «Продукт A» из первого выпадающего списка, в результате чего второй выпадающий список заполняется макетами Platinum, Gold и Silver.
  2. Пользователь выбирает «Platinum Layout» из второго выпадающего меню, в результате чего соответствующая информация отображается в сетке.
  3. Пользователь выбирает «Продукт C» из первого выпадающего списка, в результате чего второй выпадающий список снова заполняется макетами Platinum, Gold и Silver.
  4. Пользователь выбирает «Platinum Layout» из второго выпадающего списка, вызывая то же ошибочное поведение, описанное в шаге 4 Сценария 1.

Сценарий 3

  1. Пользователь выбирает «Продукт A» из первого выпадающего списка, в результате чего второй выпадающий список заполняется макетами Platinum, Gold и Silver.
  2. Пользователь выбирает «Серебряный макет» из второго раскрывающегося списка, в результате чего соответствующая информация отображается в сетке.
  3. Пользователь выбирает «Продукт C» из первого выпадающего списка, в результате чего второй выпадающий список заполняется платиновыми и серебряными раскладками.
  4. Пользователь выбирает «Серебряный макет» во втором раскрывающемся списке, в результате чего соответствующая информация отображается в сетке (как должно было происходить в двух других сценариях).

Чтобы попытаться заставить поле со списком забыть, какой элемент был выбран до отскока, я попытался вручную установить выбранный элемент в -1 (ничего) перед привязкой, используя:

layoutCombo.select (-1); * 1 061 *

и я также попытался перезагрузить поле со списком после привязки, используя

layoutCombo.reload (); * * тысяча шестьдесят-семь

Однако ни один из них не работал для меня.

Кто-нибудь еще видел такое поведение при подобных обстоятельствах? Можно ли как-нибудь вручную очистить последнюю выбранную переменную элемента поля со списком на моей странице ( без копания в источнике Telerik)?

1 Ответ

1 голос
/ 12 января 2012

Поиграв с ним немного больше и надеясь, что он просто сработает, похоже, что он сработает, если я запустил событие change вручную после layoutCombo.select(-1) и перед тем, как принудительно установить dataBind во втором поле со списком.Вот как выглядит мой productChanged код:

function productChanged(e) {
    clearLayout();
    var layoutCombo = $("#layoutList").data('tComboBox');

    if (layoutCombo == null) {
        alert("Can't find layoutList");
        return;
    }

    if (e.value == "" || e.value == null) {
        clearLayout();
        return;
    }

    layoutCombo.loader.showBusy();
    $.get('@Url.Action("GetProductLayouts", "Maintenance")', { prodID: e.value }, function (result) {
        layoutCombo.select(-1);
        layoutCombo.trigger.change(); //**** Trigger the change manually so the combobox knows its value has changed
        layoutCombo.dataBind(result);
        layoutCombo.loader.hideBusy();
    });
    //layoutCombo.reload();
}

Это похоже на хак, поскольку поле со списком должно знать, что оно уже имеет свою ценность.Любые другие идеи, чтобы сделать это чище будет высоко ценится.

...