How to refresh line chart with a drop down list event?

1 Answer 621 Views
Chart DropDownList
CHIHPEI
Top achievements
Rank 2
Iron
Iron
Iron
CHIHPEI asked on 31 Oct 2022, 01:45 AM

Scenario

I'll try to simplify my question with description and code.

I would like to refresh line chart with javascript after drop down list item was selected,

which the selected event has been triggered.

The line chart was in a partial view,

which its initial shown data was passed in with ViewBag as local data and binded with line chart .

What I've tried so far

I was able to trigger javascript with custom select event,

and retrieve the drop down list selected item,

then I'll passed the select item as a query condition back to controller,

after getting new list of data from database,

I need to pass these data back to partial view where the line chart is to refresh it.

Question1

My line chart data was first binded with ViewBag local data binding.

Should I just return to partial view and pass new data in with ViewBag,

and let it automatically refresh the chart since return back to the partial view forcelly renders it again?

Question2 (Extension of question1)

I would have 4 line charts in the partial view,

each chart has a dropdown list to refresh the chart,

If a dropdown list item was selected,

would the other chart shows nothing? Since I've binded data with ViewBag in the beggining,

If so, how can I prevent the other 3 chart to refresh(loosing data)?

Code

Partial View with line chart and drop down list (the three other linechart was not listed )

@*
    For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
   //line chart datas
    var instDatas = (MyDataViewModel)ViewBag.instsData;
}

<div>
    @(Html.Kendo().TabStrip()
              .Name("chart-tabstrip")
              .Animation(animation => animation.Open(effect => effect.Fade(FadeDirection.In)))
              .Items(tabstrip =>
              {
                  tabstrip.Add().Text("My Monitoring tab 1")
                      .Selected(true)
                      .Content(@<text>
                          <div>
                               @(Html.Kendo().DropDownList()
                              .Name("DTData-DropDown")
                              .DataTextField("InstNo")
                              .DataValueField("InstID")
                              .DataSource(source =>
                              {
                                  source.Read(read =>
                                  {
                                      read.Action("MyAction", "MyController", new {MyQueryParams});
                                  });
                              })
                              .Value("default")
                              .HtmlAttributes(new { style = "width: 250px" })
                             )
                             @(Html.Kendo().Chart(instDatas.DTDataViewModel)
                                    .Name("dtchart")
                                    .Title("dtchart")
                                    .Legend(legend => legend
                                        .Position(ChartLegendPosition.Bottom)
                                    )
                                    .ChartArea(chartArea => chartArea
                                        .Background("transparent")
                                    )
                                    .SeriesDefaults(seriesDefaults =>
                                        seriesDefaults.Line().Style(ChartSeriesStyle.Smooth)
                                    )
                                    .Series(series => {
                                        series.Line(model => model.ReadData).Name("ReadData");
                                    })
                                    .ValueAxis(axis => axis
                                        .Numeric()
                                    )
                                    .CategoryAxis(axis => axis
                                        .Categories( m => m.ReadTime)
                                        .Type(ChartCategoryAxisType.Date)
                                        .BaseUnit(ChartAxisBaseUnit.Fit)
                                        .Labels(labels => labels.Rotation(-90))
                                        .Crosshair(c => c.Visible(true))
                                        .AutoBaseUnitSteps(config => config.Milliseconds(1))
                                    )
                                    .Tooltip(tooltip => tooltip
                                        .Visible(true)
                                        .Shared(true)
                                        .Format("{0:N0}")
                                    )
                                )
                          </div>
                      </text>);                
              })
              .HtmlAttributes(new{style = "width : 1400px; margin: 30px auto"}) 
)
</div>
 
<script>
   //Dropdown list select event function(Haven't add it)
    function instDataChartDropDownSelect(e) {
        var dataItem = this.dataItem(e.item);

        var instNo = dataItem.value;
    }
</script>

1 Answer, 1 is accepted

Sort by
1
Accepted
Mihaela
Telerik team
answered on 02 Nov 2022, 03:10 PM

Hello CHIHPEI,

Thank you for the details about the scenario.

If you pass the selected DropDownList value to the server through an AJAX request, you could:

  1. Return the new dataset back to the client.
  2. Set the data to the Chart's DataSource by using the data() method.
<script>
//Dropdown list select event function()
function instDataChartDropDownSelect(e) {
        var dataItem = this.dataItem(e.item);
        var instNo = dataItem.Value;

        $.ajax({
                type: "POST",
                url: '@Url.Action("GetChartData","ControllerName")',
                data: {'selectedItem': instNo},
                dataType: 'json',
                success: function(response) {
                    $("#dtchart").data("kendoChart").dataSource.data(response);
                },
                error: function(response) {
                }
            });
    }
</script>

//Controller
public ActionResult GetChartData(int selectedItem)
{
  ...
  return Json(newChartDataSetCollection);
}

If you use this approach, you can pass the data to the respective Chart and the rest of the Charts will not be refreshed.

Another option is to return the PartialView that contains the Chart and update the add the new dataset to ViewBag. In this case, you can bind each Chart to a separate ViewBag property.

 <div id="chartsContainer"></div>

<script>
    function instDataChartDropDownSelect(e) {
        var dataItem = this.dataItem(e.item);
        var instNo = dataItem.Value;
        $("#chartsContainer").load(`/Home/GetChartData?selectedItem=${instNo}`);
    }
</script>

//Controller
public ActionResult GetChartData(int selectedItem)
{
            ViewBag.instsData = result; //set the new data;
            return PartialView("~/Views/Home/MyPartialView.cshtml");
}

 

I hope that helps.

 

Regards, Mihaela Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

CHIHPEI
Top achievements
Rank 2
Iron
Iron
Iron
commented on 03 Nov 2022, 02:52 AM

Hi Mihaela

Thanks for helping me out,

I think I'll try the first approach.

However, I've ran into another problem,

I'm not able to call the "instDataChartDropDownSelect" function, which it is in the partial view.

Because I have to get another value(name as queryParam) from viewbag in partial view as a query parameter to pass with the function,

so I had to place the script inside the partial view.

Is there any work arounds? 

I'll demo my partial view below.

Thanks again

ChihPei

MyPartialView
@*
    For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
    var instDatas = ViewBag.instsData;
    var queryParam = ViewBag.queryParam;
}

<div>
     @(Html.Kendo().DropDownList()
                                      .Name("MyDropDown")
                                      .DataTextField("InstNo")
                                      .DataValueField("InstID")
                                      .DataSource(source =>
                                      {
                                          source.Read(read =>
                                          {
                                              read.Action("MyAction", "MyController");
                                          });
                                      })
                                      .Value("default")
                                      .HtmlAttributes(new { style = "width: 250px" })
                                      .Events(e => e.Select("instDataChartDropDownSelect"))
                                   )
</div>

<!--Javascript-->
<script type="text/javascript">

    function instDataChartDropDownSelect(e) {

        var dataItem = this.dataItem(e.item);
        var instNo = dataItem.value;
        
         $.ajax({
                type: "POST",
                url: '@Url.Action("MyAction2","MyController")',
                data: {'instNo': instNo, 'queryParam': @queryParam},
                dataType: 'json',
                success: function(response) {
                    $("#dtchart").data("kendoChart").dataSource.data(response);
                },
                error: function(response) {
                }
            });
    }
</script>

 

CHIHPEI
Top achievements
Rank 2
Iron
Iron
Iron
commented on 03 Nov 2022, 03:00 AM

Here is the error shown in google browser dev tools

I've checked the main view in dev tools too,

Here is the part of the partial view which renders inside the main view,

It seems that the script in partial view was loaded.

How come the function can't be called? Is the script wasn't recognized as script?

 

CHIHPEI
Top achievements
Rank 2
Iron
Iron
Iron
commented on 03 Nov 2022, 03:31 AM

For the additional question above,

I figured out a alternative soliution,

by passing query parameters with TempData not by ViewBag.

In this case I wouldn't have to pass parameter via javascript function.

If there is any another idealize approach, I would also like to learn.

But still thanks!

Mihaela
Telerik team
commented on 07 Nov 2022, 09:47 AM

Thank you for your reply, CHIHPEI.

I would suggest the following approaches:

  • To keep the "instDataChartDropDownSelect" function in the PartialView, insert it BEFORE the TabStrip component definition:
//Partial View
@{
   //line chart datas
    var instDatas = (MyDataViewModel)ViewBag.instsData;
}

<script>
   //Dropdown list select event function
    function instDataChartDropDownSelect(e) {
      ...
    }
</script>

<div>
  @(Html.Kendo().TabStrip()
    .Name("chart-tabstrip")
    ...
  )
</div>

  • Rather than using ViewBag or TempData storage approach, you can store the required query parameter in a Model property and pass it to the Partial View.
CHIHPEI
Top achievements
Rank 2
Iron
Iron
Iron
commented on 09 Nov 2022, 12:59 AM

Thank you Mihaela,

I'll try to move my script before the TabStrip component and see if its callable.

For the second question, 

Actually, I was trying to pass query paramete from front end to action,

that's why I tend to put the script inside the partial view.

Saying that I had a query parameter was sent from Action 1 to partial view with ViewBag or TempData.

Then I'll pass the query parameter with the javascript function was called.

This might not be an idealize way to do it.

Thanks for the advice,

I'll see what I can do by using Model property

Tags
Chart DropDownList
Asked by
CHIHPEI
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
Mihaela
Telerik team
Share this question
or