Learn how to leverage REST data providers and sources to build a custom view in Kendo UI Builder.
When you're building an app, most views will need to display data from backend systems. Kendo UI Builder provides access to such data via Data Providers and their associated data sources. Currently, the product has built-in support for REST, OData and JSDO.
In this blog, we will learn how to create a custom view that renders data from a REST service. We will see how we can interface to data sources to get at the data as well as at the metadata (fields definition).
To keep things simple, we will create a custom view that renders an HTML table with the list of fields as headers and the data in additional table rows as in the following example:
To follow along, download the template samples zip from github or clone the repository. Then open the folder "custom-table-from-data-source" and follow the same steps originally outlined in this post to install this template in your target application.
The custom view can render data from any configured REST data source, but for the sake of illustration in this blog we will render a list of metrics from IoT devices. The device metrics are provided by the same test REST server we setup in a blog post from earlier in this series.
If you have not set them up yet, please refer to the detailed instructions in the prerequisites section of the same post.
From the Kendo UI Builder view property panel, our custom view users should be able to select the data provider and the data source to use.
We add the following definitions to the definition file (See custom-table-from-data-source.json).
If you've been following along in our Kendo UI Builder series, most properties should be familiar to you by now, but if not you may want to head back and read the post where I first introduced custom views.
The key thing here is the editorType for each property.
Now at design-time, we will be able to select where the data is coming from with a few clicks in the property panel.
We want to give our users a feel for how the table will render.
To achieve this, we need to take care of two main items:
As we learned in the earlier post on augmenting models, we need to implement the function augmentModel in index.js to provide these two items.
To access the list of fields: the fields are available in a json file in the app sub-directory: “/meta/dataProviders/”. The file name is based on the data provider name as defined by the user, in my sample, I named it IoT, thus the file relative file path is /meta/dataProviders/IoT.json.
So, the goal is to read the list of fields from the metadata directly from the file system. This entails creating the path to the file, reading the file, parsing it as JSON and accessing from the JSON data, the array of fields for the specific data source.
There are two key things to keep in mind to achieve this:
The data provider name is available in the input metadata model variable (metaModel)
The data source name is also available in the metamodel input variable. For more details on it, in design/index.js, check the function getFieldsFromDataSource.
Finally, to generate some data, we simply create an array of 10 object literals. Object properties are populated by looping data source fields and adding some fake values. We generate different data for number fields versus all other fields. In design/index.js, you'll find the function createSampleDataForEachField
We also take care of rendering the custom view with dummy fields and data when no data provider or data source are selected. In design/index.js, see the function createSampleFieldsAndDataWhenNoDataSource for this.
All in all, implementing this was not so straightforward: it helped me to have some debug data. So, along the way, I stored various data points in metaModel variable and output them in the designer view.
There are two main items we want to render in our table:
To get the field names, we use same strategy as in design time view. We read the names from the metadata JSON file and store them as an array in the metaModel. We've already learned this technique from the previous blog post on Augmenting Models (see the section "Run-Time Model").
This is done in the views/custom-table-from-data-source/angular/generator/index.js, augmentModel function like so:
We store the list of fields in myDataSrcFields. We will use this variable when we need to retrieve the field names when rendering.
I have provided a set of utilities in the form of templated typescript code. Check out the folder views/custom-table-from-data-source/angular/data-services. I won’t go into the details of each file - treat them as a black box to help you when you need it.
However, it’s worth pointing out that in views/custom-table-from-data-source/angular/data-services/data-properties-initialization.ts.ejs, we have the definition for the $dataServices object literal. This object contains a data service for each data source. This will be used in ngOnInit (__name__.view.base.component.ts.ejs). Here's the relevant code extract:
We get the view data source and access the view data service.
We call the dataChanges function on the data service. The dataChanges function returns an RxJs observable. Check out this overview to learn more if you aren't familiar with those.
When the RxJs stream has received its data, we store it in the member variable myRestList ready for rendering in the view component.
Now this is comparatively the easier part 😊.
We render the headers by iterating through the variable myDataSrcFields and outputing a table cell for each field like this:
To render the data: For all items received from the server, we output a table row. Within the row, we simply output the value for each of the REST field. Notice that we loop through the data from REST server at run-time but we loop through at code generation time. Here is the code extract:
We have learned how to interface with data providers and data sources so that we can render a sample table at design-time, leverage the data services to access the data from a REST server and finally render that data at run-time.
We will use the techniques we learned here to build a card UI in a future post in this series - stay tuned!
If you jumped into this series in the middle and want to start from the beginning, you can find the previous blog posts here:
Subscribe to get all the news, info and tutorials you need to build better business apps and sites
You have the right to request deletion of your Personal Information at any time.
You can also ask us not to pass your Personal Information to third parties here: Do Not Sell My Info
We see that you have already chosen to receive marketing materials from us. If you wish to change this at any time you may do so by clicking here.
Thank you for your continued interest in Progress. Based on either your previous activity on our websites or our ongoing relationship, we will keep you updated on our products, solutions, services, company news and events. If you decide that you want to be removed from our mailing lists at any time, you can change your contact preferences by clicking here.
Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.Learn More