Motivation
Recently we have grown to like staticCommands in our DotVVM applications. They are fast, they save on network traffic and they are easy for our UX team to modify.
Grids, Pagers, and Repeaters have served us very well, however, they were not designed with static commands in mind. That makes using them in static-command-only applications impossible. The repeater works fine. It does not care as long as the DataSource property is set. GridView and Pager on the other hand have ordinary commands baked into them. As soon as you use GridView sorting or go to the next page using the current pager, you are forced to do a full postback.
In this design document, we present changes to enhance and modernize GridView, Repeater, Pager, and GridViewDataSet with static commands in mind.
Example of proposed features in use:
<body>
<DataControls.TemplateProvider>
<dot:CustomTemplateProvider>
<PagerFirstTemplate>
<!-- ... //-->
</PagerFirstTemplate>
<!-- ... //-->
<GridColumnHeaderTemplate>
<span>
<cc:Icon Type="{value: _column.Name}">
<dot:LinkButton Click={staticCommand: Sorter.Sort(_column.Name)} Text={value: _column.Name}/>
</span>
</GridColumnHeaderTemplate>
</dot:CustomTemplateProvider>
</DataControls.TemplateProvider>
<!-- ... //-->
<form>
<dot:TextBox Value={value: SearchText} />
<dot:Button Click={staticCommand: Customers.Pager.Page(0); Customers.RequestRefresh()} Text="Search"/>
</form>
<dot:DataSetLoader DataSource={value: Customers} Load={staticComand: options => service.CustomersGrid(options, SearchText)} />
<dot:GridView DataSource={value: Customers} >
<!-- ... //-->
</dot:GridView>
<dot:Pager DataSource={value: Customers} />
</body>
DataSet design
GridViewDataSet has the Items property, same as before
Pager, Sorter, Filter properties are moved to separate DTO under the Options property. This makes passing the options as an argument easier. For example when calling a service method as a static command. There is little reason to send grid items back to a server.
RequestRefresh() method on the data set has its javascript translator registered so it works when called in a static command. When called from a static command it updates the data set options in javascript, then finds a loader callback and reloads the items from the server.
Pager object has methods like First(), Previous(), Page(int index), Next(), Last(). These methods have their default implementation in C# that is used if called from standard command. However, those methods also have their javascript translations registered for use from a static command.
Sorter has the method Sort(...) that also has the C# equivalent for commands and javascript translation for static commands.
The new DataSetLoader control
The reason for this control is to decouple data source loading from the controls like grids, pagers, and other controls meant to display the data.
- Property
DataSource binds a loader to a data source. Multiple grids and repeaters can display the data source, but for each data source, there is only one loader.
- Command Property
Load static command containing a lambda function that returns filled GridViewDataSet. Example: (DataSetOptions opt) => myService.MyLoad(opt,...).
How it works
On client javascript code, the loader is connected with a grid, repeater, pager, or any other items control by using the same object in their DataSource property.
When GridViewDataSet.RequestRefresh() is called from a static command the DataSetLoader for the data set is located. Then lambda function from property DataSetLoader.Load is called and the data set is updated with the new data returned from the server. This is part of javascript translation for the GridViewDataSet.RequestRefresh method.
DataControls.TemplateProvider Extension property
In the past, it has been very hard to customize DotVVM Pager and GridView controls. For this reason, we created DataControls.TemplateProvider. The property is inherited from parent elements. It can be set for instance in a master page on body and it will affect all grids and pagers in the application.
The property contains controls derived from DataControlsTemplateProvider. We created default Template providers to choose from:
CommandTemplateProvider - is the default. All the interactions like sorting and paging are handled by ordinary command bindings and will result in postbacks.
StaticCommandTemplateProvider - All the interactions like sorting and paging are handled by stratic command bindings. Here, javascript translations of methods on GridViewDataSet get called.
CustomTemplateProvider - This provider contains template properties that allow the user to specify the markup themselves:
PagerFirstTemplate - Pager first button content
PagerNextTemplate - Pager next button template
PagerPageNumberTemplate - Pager page item button template
PagerPreviousTemplate - Pager previous button template
PagerLastTemplate - Pager last button template
ColumnHeaderTemplate - GridView column header template
Motivation
Recently we have grown to like staticCommands in our DotVVM applications. They are fast, they save on network traffic and they are easy for our UX team to modify.
Grids, Pagers, and Repeaters have served us very well, however, they were not designed with static commands in mind. That makes using them in static-command-only applications impossible. The repeater works fine. It does not care as long as the
DataSourceproperty is set. GridView and Pager on the other hand have ordinary commands baked into them. As soon as you use GridView sorting or go to the next page using the current pager, you are forced to do a full postback.In this design document, we present changes to enhance and modernize
GridView,Repeater,Pager, andGridViewDataSetwith static commands in mind.Example of proposed features in use:
DataSet design
GridViewDataSethas theItemsproperty, same as beforePager,Sorter,Filterproperties are moved to separate DTO under theOptionsproperty. This makes passing the options as an argument easier. For example when calling a service method as a static command. There is little reason to send grid items back to a server.RequestRefresh()method on the data set has its javascript translator registered so it works when called in a static command. When called from a static command it updates the data set options in javascript, then finds a loader callback and reloads the items from the server.Pagerobject has methods likeFirst(),Previous(),Page(int index),Next(),Last(). These methods have their default implementation in C# that is used if called from standard command. However, those methods also have their javascript translations registered for use from a static command.Sorterhas the methodSort(...)that also has the C# equivalent for commands and javascript translation for static commands.The new DataSetLoader control
The reason for this control is to decouple data source loading from the controls like grids, pagers, and other controls meant to display the data.
DataSourcebinds a loader to a data source. Multiple grids and repeaters can display the data source, but for each data source, there is only one loader.Loadstatic command containing a lambda function that returns filledGridViewDataSet. Example:(DataSetOptions opt) => myService.MyLoad(opt,...).How it works
On client javascript code, the loader is connected with a grid, repeater, pager, or any other items control by using the same object in their
DataSourceproperty.When
GridViewDataSet.RequestRefresh()is called from a static command theDataSetLoaderfor the data set is located. Then lambda function from propertyDataSetLoader.Loadis called and the data set is updated with the new data returned from the server. This is part of javascript translation for theGridViewDataSet.RequestRefreshmethod.DataControls.TemplateProvider Extension property
In the past, it has been very hard to customize DotVVM
PagerandGridViewcontrols. For this reason, we createdDataControls.TemplateProvider. The property is inherited from parent elements. It can be set for instance in a master page onbodyand it will affect all grids and pagers in the application.The property contains controls derived from
DataControlsTemplateProvider. We created default Template providers to choose from:CommandTemplateProvider- is the default. All the interactions like sorting and paging are handled by ordinary command bindings and will result in postbacks.StaticCommandTemplateProvider- All the interactions like sorting and paging are handled by stratic command bindings. Here, javascript translations of methods onGridViewDataSetget called.CustomTemplateProvider- This provider contains template properties that allow the user to specify the markup themselves:PagerFirstTemplate- Pager first button contentPagerNextTemplate- Pager next button templatePagerPageNumberTemplate- Pager page item button templatePagerPreviousTemplate- Pager previous button templatePagerLastTemplate- Pager last button templateColumnHeaderTemplate- GridView column header template