Skip to content

CodeCoupler UI DataSource

All components of the CodeCoupler framework (System, Stage, Application, Widget) can create so named data sources. A data source is a library which handles a set of data objects and CRUD operations on it.

We will provide here a brief description of a data source. Basically CodeCoupler use the data source library of Kendo UI Core whose API can be read in detail here:

Quick Overview of Options and Methods

A data source will be created with some options which define how to receive data from a remote endpoint and how to transfer modifications:

1
2
3
4
5
6
7
8
{
  transport: {
    read: {}, //Define how to read data
    create: {}, //Define how to transfer new created data
    destroy: {}, //Define how to transfer deleted data
    update: {}, //Define how to transfer updated data
  }
}

A data source use models which can separately defined (and it is recommended to do so). A model define the fields and types of them:

1
2
3
4
5
6
7
8
9
var model = kendo.data.Model.define({
  id: "todoId",
  fields: {
    description: { type: "string" },
    priority: { type: "number" },
    done: { type: "boolean" },
    deadline: { type: "date" },
  },
});

Absolute minimum is fieldName: {}. The id field must not be defined in fields. If defined it should be not editable idFieldName: {editable:false}.

The basic field configuration properties for each field are:

type: String

The available options are string, number, boolean, date and object.

editable: Boolean

Specifies if the field is editable or not. Defaults to true.

nullable: Boolean

Specifies if the defaultValue setting will be used. If set to true, the defaultValue will be ignored and new models will be created with null field value. Defaults to false.

defaultValue: Any

The default value for string is "", for number is 0, and for date is new Date() (today). Even not documented the default value for boolean seems to be false. The parameter can also be set to a function that returns the dynamic default values.

from: String

Specifies the field of the original record whose value is used to populate the Model field. When CRUD operations (specifically adding new items) are enabled, the original field name should be defined with a defaultValue as well.

parse: function(value)

Specifies the function which will parse the field value. If not set default parsers will be used.

These models can be defined in the configuration property schema.model:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  transport: {
    read: {}, //Define how to read data
    create: {}, //Define how to transfer new created data
    destroy: {}, //Define how to transfer deleted data
    update: {}, //Define how to transfer updated data
    schema: {
      model: model //Define here the model schema
    }
  }
}
validation: Object

Specifies the validation options which will be used by the Kendo UI Validator. The rules are documented here: [https://docs.telerik.com/kendo-ui/controls/editors/validator/rules]

visual: Object

This is not an official configuration option. Some parts of the CodeCoupler framework use this object to represent this field in the UI. For now the following parts use this extension: Grid, DSMValidate.

Once you have initialized a data source you can read the data from the remote endpoint with read(). With data() or view() you get an array of data items.

  • With add(new model()) you can add new data items to this array.
  • On each data item you can use the method set(field,value) to modify a value of a field.

All changes will be tracked until you call the method sync() which will transfer all modifications to the remote endpoint.

Data Sources in CodeCoupler

Normally you create a data source with new kendo.data.DataSource(options). CodeCoupler components provide a method dataSource() which create data sources as well but with enhanced possibilities.

You can use this method exactly like the origin kendo method if you like.

Note that the options will always be merged with the options defined in the system wide setting in data.options!

The main difference are mixins that can be used to extend Kendo UI Core data sources with special features. To create a data source with CodeCoupler you call the method with the following arguments:

1
2
3
4
5
6
7
//myComponent is an instance of an System, Stage, Application or Widget
var myDataSource = myComponent.dataSource({
  id: "", //Optional: Set here an id for this data source
  mixins: [], //Optional: Define a set of mixins to extend the functionality
  useSettings: true, //Optional: if true (default) mixins and options defined in settings will be used
  options: {}, //Optional: Define here the options like in any Kendo UI Core data source
});

Each mixin will extend the the origin Kendo UI DataSource in the following order:

  • Extend with mixins defined in the system wide settings array data.mixins beginning from the first mixin in the array to the last one.
  • Extend with mixins defined in the arguments array mixins beginning from the first mixin in the array to the last one.

Consequently the last mixin will execute its methods first following the other mixins in the array in reverse order. The order of executing the mixins is in some cases important.

Special Pointer to Component

Any datasource created with the component method dataSource will be created with an additional options property component. This property points to the component which created the datasource.

You can read this property from an active datasource instance with: datasource.options.component.

Testing Data Sources

To create quickly a data source without defining a remote endpoint for testing purposes you can use the configuration property data:

1
2
3
4
5
6
7
8
9
var myDataSource = x.dataSource({
  options: {
    data: [
      { todoId: 1, description: "one", priority: 0, done: false, deadline: new Date() },
      { todoId: 2, description: "two", priority: 0, done: true, deadline: new Date() },
      { todoId: 3, description: "three", priority: 1, done: false, deadline: new Date() },
    ],
  },
});

Best Practice / Extending Base Class

It is a good idea to write an own module for each model or endpoint you use. This module should include the model and a mixin that extends a datasource pointing to the endpoint:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import kendo from "kendo-ui-core";
import $ from "jquery";

export const model = kendo.data.Model.define({
  id: "yourId",
  fields: {
    /* Define here the model fields */
  },
});

export const mixin = (superclass) =>
  superclass.extend({
    init: function (options) {
      let settings = {
        schema: {
          model: model,
        },
        transport: {
          /* Define here transport settings pointing to the endpoint */
        },
      };
      superclass.fn.init.call(this, $.extend(true, {}, options, settings));
    },
  });

Furthermore you could set default values for all dataSources before starting any system:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import { System, DSMLoopback } from "@codecoupler/cc-ui";
//Add mixins that should be used by each dataSource
System.settings.data.mixins.push(DSMLoopback);
//Define some options that will be used by each DataSource.
//Here we define for example that all dataSources use a loopback
//API and we set the base path. Each module for each model have
//now to define only the "controller" property.
$.extend(true, System.settings, {
  data: {
    options: {
      type: "loopback",
      transport: {
        base: "/your/base/path",
      },
    },
  },
});

Now you can create a datasource pointing to the endpoint by:

1
2
3
4
import { mixin as MyEndpoint } from "./my-module";
myComponent.dataSource({
  mixin: [MyEndpoint],
});