Thanks, adding
this.GetCmp<CartesianChart>(string.Empty);
ensured that the chart script was loaded. The page will always contain at least one chart, so this seems like the best approach.
However, have run into a problem with binding a chart to a store. I have the following Razor page that is returning component content to a parent page.
public class BookingsByMonthModel : PageModel
{
private readonly IQueryHandler<GetBookingsByMonthQuery, List<BookingsByMonth>> _queryHandler;
private readonly ISerializationService _serializationService;
private const string StoreId = "bookingsByMonthStore";
public BookingsByMonthModel(
IQueryHandler<GetBookingsByMonthQuery, List<BookingsByMonth>> queryHandler,
ISerializationService serializationService)
{
_queryHandler = queryHandler;
_serializationService = serializationService;
}
public async Task<IActionResult> OnGetAsync()
{
var store = new Store
{
Data = (await _queryHandler.HandleAsync(new GetBookingsByMonthQuery(2020)))
.Select(obj => new { Month = obj.MonthName, Bookings = obj.CountOfBookings })
.OfType<object>()
.ToList(),
StoreId = StoreId,
Fields = new List<DataField>
{
new DataField { Name = "month" },
new DataField { Name = "bookings" }
}
};
var panel = new Panel
{
Layout = LayoutType.Column,
Items =
{
new Panel
{
ColumnWidth = 0.6,
Items =
{
new CartesianChart
{
Width = 600,
Height = 300,
Store = StoreId,
Axes = new List<Axis>
{
new NumericAxis
{
Position = Position.Left,
Fields = "bookings",
Grid = true,
Title = "Bookings",
Minimum = 0
},
new CategoryAxis
{
Position = Position.Bottom,
Fields = "month",
Title = "Month"
}
},
Series = new List<Series>
{
new BarSeries
{
Highlight = true,
XField = "month",
YField = "bookings",
Tooltip = new SeriesTooltipModel
{
TrackMouse = true,
Width = 140,
Height = 28,
Renderer = "function (toolTip, storeItem) { toolTip.setTitle(Ext.String.format('{0}: {1}', storeItem.get('month'), storeItem.get('bookings'))); }"
}
}
}
}
}
},
new Panel
{
ColumnWidth = 0.4,
Items =
{
new GridPanel
{
Width = 500,
Height = 300,
Frame = true,
Store = StoreId,
Columns = new List<Column>
{
new Column { Text = "Month", DataIndex = "month", Flex = 1 },
new NumberColumn { Text = "Bookings", DataIndex = "bookings", Format = "0" }
}
}
}
}
}
};
var serializedControls = new StringBuilder();
using var writer = new StringWriter(serializedControls);
_serializationService.Serialize(new object[] { store, panel } , writer);
return Content(serializedControls.ToString(), "application/json", Encoding.UTF8);
}
The following JSON content is returned by the page:
[{storeId:"bookingsByMonthStore",type:"store",fields:[{name:"month",type:"auto"},{name:"bookings",type:"auto"}],data:[{"month":"Jan","bookings":23},{"month":"Feb","bookings":34},{"month":"Mar","bookings":58},{"month":"Apr","bookings":45},{"month":"May","bookings":45},{"month":"Jun","bookings":1},{"month":"Jul","bookings":21},{"month":"Aug","bookings":16},{"month":"Sep","bookings":0},{"month":"Oct","bookings":1},{"month":"Nov","bookings":9},{"month":"Dec","bookings":4}]},{xtype:"panel",items:[{columnWidth:0.6,xtype:"panel",items:[{height:300,width:600,xtype:"cartesian",axes:[{fields:"bookings",grid:true,minimum:0,position:"left",title:"Bookings",type:"numeric"},{fields:"month",title:"Month",type:"category"}],series:[{highlight:true,tooltip:{height:28,width:140,xtype:"tooltip",trackMouse:true,renderer:function (toolTip, storeItem) { toolTip.setTitle(Ext.String.format('{0}: {1}', storeItem.get('month'), storeItem.get('bookings'))); }},type:"bar",xField:"month",yField:"bookings"}],store:"bookingsByMonthStore"}]},{columnWidth:0.4,xtype:"panel",items:[{frame:true,height:300,width:500,xtype:"gridpanel",columns:[{flex:1,xtype:"gridcolumn",dataIndex:"month",text:"Month"},{xtype:"numbercolumn",dataIndex:"bookings",text:"Bookings",format:"0"}],store:"bookingsByMonthStore"}]}],layout:"column"}]
When the page is being rendered, I get the following error reported in the browser console:
Cannot read property 'getData' of undefined
I can see that this error is occurring because there's no store bound to the chart. If I change my Razor page code to create the store inline within the chart, it works. However that means that I can't use one store as the data source for both the chart and grid. The grid renders fine using the external store id, it's only the chart that won't render.
How do you suggest I can configure my page so that both the chart and grid can share the same store and both can render successfully?
Thanks
Paul