This is a migrated thread and some comments may be shown as answers.

Server fIlter on chart datasource doesn't work

3 Answers 275 Views
Chart
This is a migrated thread and some comments may be shown as answers.
Milos
Top achievements
Rank 1
Milos asked on 07 Sep 2018, 01:20 PM

     Hi, here is the problem. I have mvc chart set in razor view. Here is the definition:

    <div class="demo-section k-content wide">
                @(Html.Kendo().Chart<List<Novolyze.VOD.WebUI.Models.ChartSource>>()
                .AutoBind(false)
                .DataSource(dataSource => dataSource            
                .Read(read => read
                    .Action("DailyStatisticJson", "Production")
                    //.Data("getFilterParams")
                )
                .Group(group => group
                    .Add<string>("SeriesName"))
            
                )           
                .Name("dailyStatisticChart")
                .Title("Daily Statistic")
                .Zoomable(zoomable => zoomable
                    .Mousewheel(mousewheel => mousewheel
                        .Lock(ChartAxisLock.Y))
                    .Selection(selection => selection
                        .Lock(ChartAxisLock.Y)))
                .Pannable(pannable => pannable
                    .Lock(ChartAxisLock.Y))
                .Legend(legend => legend
                    .Visible(false)
                )
                .SeriesDefaults(seriesDefaults => seriesDefaults
                    .Column()
                .Stack(true)
                )
                .Series(series => series
                    .Column(model => model).Field("Value").CategoryField("Category").ColorField("ColorName")
                )                    
                .CategoryAxis(axis => axis
                    .Date()
                    .BaseUnit(ChartAxisBaseUnit.Days)
                    .Labels(labels => labels
                        .Rotation("auto"))
                )                    
            )

I also have contlroler method:

public ActionResult DailyStatisticJson([DataSourceRequest] DataSourceRequest request)
{    

  //Some logic and return datasource JSON, that works well

}

I want to refresh the chart with new data based on some external filtering. I have the following Javascript code that should do the trick, but it doesn't

 function executeFilter(filters) {  
        var chart = $("#dailyStatisticChart").data("kendoChart");
        if (chart) {
            chart.dataSource.filter(filters);
            //chart.dataSource.read();                   
        }
    }    

The point is: if I call just filter() and not the read(), chart data disappear, controller is not called. If I uncomment read(), then controller is called, but filter property is empty in the controller parameter. I can find the workaround to pass additional data with uncommenting Data to datasource definition but then I will use another param in controller, not DatasourceRequest, which will be uglier. Is there a solution with filter?

3 Answers, 1 is accepted

Sort by
0
Tsvetina
Telerik team
answered on 11 Sep 2018, 09:42 AM
Hi Milos,

There might be a problem with the format of the request when filtering criteria is added. Could you try declaring your DataSource like this:
.DataSource(ds => ds
    .Custom()
    .Schema(schema=>schema.Data("Data"))
    .Transport(transport=> {
        transport.Read(r => r.Action("DailyStatisticJson", "Production"));
    })
)

and the controller method signature and structure like this:
public ActionResult DailyStatisticJson([DataSourceRequest]DataSourceRequest request)
{
    // obtain a reference to the unfiltered data set or context
    var result = ...
    // call ToDataSourceResult() to apply the filtering
    return Json(result.ToDataSourceResult(request));
}

If this change doesn't help, check the browser developer tools (F12 key) Network tab for any failed requests to the server and if there are any, check their response for server error messages.

Regards,
Tsvetina
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Milos
Top achievements
Rank 1
answered on 12 Sep 2018, 07:56 AM
There is no change in your solution comparing to mine, except if you think on blank space in method argument. That is not a problem. There is also no error, nor failed request, just filter is empty. OK, I will try to help with as much details as I found. 

Point is that when filter method from chart datasource is called it does not create filter field in post body like grid datasource filter method. Grid filter method formats it in some way with some ~ characters, and chart filter simply put filter arguments as an array in post body. Because of that reason, when filter called from a grid, i get filter property in DataSourceRequest argument in controller filled as it should be and in the case of chart filter called filter property in the controller argument is empty. 
Conclusion is that model binder [DataSourceRequest] doesn't know how to interpret array from post body and put it into an object.

So, the problem is why chart.datasource.filter doesn't format filter like grid.datasource.filter
I saw that datasources for grid and chart are different objects. Argument in datasource method for grid is DataSourceBuilder and for chart is ReadOnlyAjaxDatasourceBuilder.
Obviously the first one knows how to create filter, the second one doesn't know which means that chart can't have filter feature.

Please just confirm to me if this is correct or I can use filter for chart on some other way. 
0
Tsvetina
Telerik team
answered on 13 Sep 2018, 02:44 PM
Hello Milos,

My suggestion included also a Custom DataSource, so that its schema can be configured to parse the DataSourceResult returned by the server. You would still needed it, but after your description, I think I know what else is missing.

When using the Chart with a regular DataSource, it makes a GET request by default, while the Grid DataSource makes a POST request when default configuration is used. So, the custom DataSource also needs to use the POST verb:
.DataSource(ds => ds
    .Custom()
    .Schema(schema => schema.Data("Data"))
    .Transport(transport =>
    {
        transport.Read(r => r.Action("DailyStatisticJson", "Production").Type(HttpVerbs.Post));
    })
)

To demonstrate that a Chart should work with such a configuration, I am attaching a sample project, where a Chart is filtered externally on button click (bin folder is removed, so the references need to be restored before running the sample).

Following is the relevant code from the sample if you only want to view it:
<button onclick="filter()">Show values > 100</button>
@(Html.Kendo().Chart<TelerikMvcApp12.Models.ProductViewModel>()
    .Name("chart")
    .Series(series => series
        .Column(model => model).Field("UnitsInStock").CategoryField("ProductName")
    )     
    .DataSource(ds => ds
        .Custom()
        .Schema(schema => schema.Data("Data"))
        .Transport(transport =>
        {
            transport.Read(r => r.Action("Products_Read", "Grid").Type(HttpVerbs.Post));
        })
    )
)
<script>
    function filter() {
        var chart = $("#chart").data("kendoChart");
        chart.dataSource.filter({field: "UnitsInStock", operator: "gt", value: 100});
    }
</script>

public ActionResult Products_Read([DataSourceRequest]DataSourceRequest request)
{
    var result = Enumerable.Range(1, 20).Select(i => new ProductViewModel
    {
        ProductID = i,
        UnitsInStock = i * 10,
        ProductName = "Product " + i,
        Discontinued = i % 3 == 0
    });
 
    return Json(result.ToDataSourceResult(request));
}


Regards,
Tsvetina
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
Chart
Asked by
Milos
Top achievements
Rank 1
Answers by
Tsvetina
Telerik team
Milos
Top achievements
Rank 1
Share this question
or