Skip to content

Better data controls - Design #1007

Description

@Mylan719

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions