Telerik Grid с несколькими столбцами и 1 фильтром, проблема с внешним ключом Guid - PullRequest
0 голосов
/ 29 октября 2018

У меня есть Kendo Grid, теперь для тестирования только с 4 столбцами. Каждый столбец имеет разные типы: string, DateTime, int и ForeignKey of Guid! Проблема возникает здесь: я хочу отфильтровать свою сетку, набрав что-нибудь в моем единственном текстовом поле фильтра, но Grid не может быть отфильтрован в столбец ForeignKey, потому что я, конечно, набираю видимый текст, а не Guid ...

Моя простая ViewModel:

public class ClientViewModel
{
    public Guid Id { get; set; }
    public string FullName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public int ZipCode { get; set; }
    public Guid CityId { get; set; }
}

По предложению поддержки Telerik я использую собственный источник данных для своей сетки (кстати, они все еще не могут дать мне правильный способ решения этой проблемы). Вид выглядит так:

@(Html.Kendo().Grid<ClientViewModel>().Name("clientGrid")
  .Events(ev => ev.Edit("onEdit"))
  .Columns(c =>
  {
      c.Bound(x => x.Id).Hidden(true);
      c.Bound(x => x.FullName);
      c.Bound(x => x.DateOfBirth).Format("{0:yyyy.MM.dd.}");
      c.ForeignKey(x => x.CityId, (IEnumerable) ViewData["City"], "Id", "Name");
      c.Bound(x => x.ZipCode);
  })
  .ToolBar(t =>
  {
      t.Template(@<text>
              <div>
                  <label class="search-label" for="searchBox">Search:</label>
                  <input type="search" id="searchBox" class="k-textbox" style="width: 250px"/>
                  <input type="button" id="clearBox" value="Clear filters" class="k-primary" style="height: 1.65em;"/>
              </div>
           </text>);
  })
.DataSource(source => source
                .Custom()
                .Type("odata-v4")
                .Schema(sch => sch.Model(m =>
                {
                    m.Id(p => p.Id);
                    m.Field(p => p.Id).DefaultValue(Guid.NewGuid());
                    m.Field(p => p.FullName);
                    m.Field(p => p.DateOfBirth);
                    m.Field(p => p.CityId).DefaultValue(Guid.Empty);
                    m.Field(p => p.ZipCode);
                }))
                .Transport(tr =>
                {
                    tr.Read(read => read.Url("result.json"));
                    tr.ParameterMap("parameterMap");
                })
                )
                .Scrollable()
                .Filterable()
                .Sortable()
                .HtmlAttributes(new { style = "height: 700px;" })
                .Pageable(p => p.Refresh(true).PageSizes(true).ButtonCount(5)))

Часть javascript:

function parameterMap(options, operation) {
    var result = kendo.data.transports["odata-v4"].parameterMap(options, operation);

    if (result.$filter) {
        var guid = /('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')/ig;

        result.$filter = result.$filter.replace(guid, function (x) {
            return x.substring(1, x.length - 1);
        });
    }

    return result;
}

function isNumeric(n) {
    return !isNaN(parseFloat(n)) && isFinite(n);
}

$(document).ready(function () {

    var grid = $('#clientGrid').data('kendoGrid');

    $('#searchBox').on('input',
        function (e) {
            var columns = grid.columns;
            var filter = { logic: 'or', filters: [] };
            columns.forEach(function (x) {

                if (x.field) {
                    var type = grid.dataSource.options.schema.model.fields[x.field].type;
                    var defaultValue = grid.dataSource.options.schema.model.fields[x.field].defaultValue;

                    if (type === 'string') {
                        filter.filters.push({
                            field: x.field,
                            operator: "contains",
                            value: e.target.value
                        });
                    } else if (type === 'number') {
                        if (isNumeric(e.target.value)) {
                            filter.filters.push({
                                field: x.field,
                                operator: 'eq',
                                value: e.target.value
                            });
                        }
                    } else if (type === 'date') {
                        var data = grid.dataSource.data();
                        for (var i = 0; i < data.length; i++) {
                            var dateStr = kendo.format(x.format, data[i][x.field]);
                            if (dateStr.startsWith(e.target.value)) {
                                filter.filters.push({
                                    field: x.field,
                                    operator: 'eq',
                                    value: data[i][x.field]
                                });
                            }
                        }
                    }
                }
            });

            grid.dataSource.filter(filter);
        });

    $('#clearBox').click(function(e) {
        grid.dataSource.filter({});
        $('#searchBox').val('');
    });
});

Модель для ViewData ["City"] использует следующий класс City:

public abstract class BaseEntity
{
    protected BaseEntity()
    {
        Id = Guid.NewGuid();
    }

    [Key]
    public Guid Id { get; set; }
}

public class Country : BaseEntity
{
    public Country()
    {
        Cities = new HashSet<City>();
    }

    [Required]
    [StringLength(250)]
    public string Name { get; set; }

    [Required]
    [StringLength(3)]
    public string Code { get; set; }

    public virtual ICollection<City> Cities { get; set; }
}

public class City : BaseEntity
{
    public City()
    {
        Clients = new HashSet<Client>();
    }

    [Required]
    [StringLength(250)]
    public string Name { get; set; }

    public int ZipCode { get; set; }

    public Guid CountryId { get; set; }

    [ForeignKey("CountryId")]
    public virtual Country Country { get; set; }

    public virtual ICollection<Client> Clients { get; set; }
}

public class Client : BaseEntity
{
    [Required]
    public string FullName { get; set; }

    public DateTime DateOfBirth { get; set; }

    public Guid CityId { get; set; }

    [ForeignKey("CityId")]
    public virtual City City { get; set; }
}

Фильтрация работает отлично, если я ввожу какой-либо текст, целое число или дату, но когда я пытаюсь отфильтровать любой из городов, она работает, только если я ввожу путеводитель по городу. Это не очень удобно для пользователя ...

Буду признателен за любую помощь

...