davinci components

overview


components are units of functionality that are bundled together as a single unit, typically as a javascript module. Components are things like charts or tables, although they do not necessarily require a visual aspect.

Component Requirements


In order to design a component, you must write your code to comply with the component specification. The primary requirement for a component is that it is encoded in javascript module as below.

export function constructor(config, options){
  this.config = config;
}
The module should contain an exported function named "constructor" which is an object constructor that takes a config as a parameter. The config should be set on the object itself as above. The options is an additional dictionary passed in by the platform that specifies additional options on the component. For simple components this can be ignored.

Component Config


The component config contains information needed by the platform to appropriately run the component. In addition, it should save whatever details are required by the component to run itself properly. That is, you should saved information about the state of teh component in the config. However, because the platform needs to save information in the config as well, there are only two properties available for components to save data in:
  • attributes
  • body
You are free to structure the data any way you wish, although typically these properties should be set as dictionaries that you can save information into.

The component script is provided in the "script" property of the config. This should be the URL of the javascript library (see above) that implements the component. When the component is added to the workspace or blog, the script is loaded and then an instance of teh component is instantiated by calling new on the "constructor" method, passing the config into the constructor.

If the component is a visual component that may have children elements (i.e. elements that can be inserted into them) then the config should have a property named "children" that is set to an empty array. This array will be populated with the configs of any child component inserted into the component itself.

config spec

Adding a Component


Adding a component to a blog or a workspace is easy, just by calling the $page.add method.

await $page.add(config);

Sample Component


The following is a simple example of a fully functional component. Assume the following code is saved at the URL '/server/sample.js'

export function constructor(config, options){
  this.config = config;
  alert('hello');
}
Then the following code adds the component

$page.add({
  script:'/server/sample.js'						
})
This component doesnt do anything other than create an alert dialog on instantiation. However, it is a fully compliant component.

Lifecycle Methods


The sample component, while compliant, is not very functional. In order to provide additional functionality, the platform will call a set of methods on the component in order to manage it through its lifecycle. We refer to these methods as lifecycle methods. Lifecyle methods are called using the dependency injection framework.

$libraries : for components that are dependent on libraries (not other modules) that need to be loaded before the component can function, you can implement a method named "$libraries" that returns an array of urls that need to be loaded.
$copy : $copy is a method that is called when a component is copied by the user, typically by click ctrl-c. The method should return a copy of the config that should be placed in the clipboard. This is useful if the copied config should be different from the config of the ctrl.

if this method is not present, the config that is copied to the clipboard matches the config of the component in the blog or workspace that is being copied.
$css : $css is similar to $libraries above. It returns any urls that represent style sheets that need to be loaded
$html : For components that need to insert html into the page, the $html method needs to be implemented. It returns html that will be inserted by the platform. Typically, you will need to use the $id service to create an id for the html. The following is a typical example

this.$html = function($id){
  return '<div id="'+$id(this.config.id)+'"></div></div>'					
}
					
Usually, it is not required to return much more html than a simple div, as the $process method, given below is called right after the html is inserted (assuming that is present on the component).
$process : The $process method is called right after a components html has been inserted. If the component has no html, the $process method is still called. For components that retrieve data or some other non-visual action, the $process method is the primary method that implements the components functionality.

For components that have more complex html, the process method can be used to insert html into its html container. In such a case, the $process method should use the $id service to get the id of the inserted html.
$remove : The $remove method is called when the component is removed from the page. This gives the component a chance to clean itself up by removing its html and any data it may have place ont the data bus.
$imports : When a component uses data that is provided by another component, such as a chart displaying data provided by a data component, the component gets acces to that data through the data bus. If a component is dependent on data on the bus, it should implement the $imports method. This method returns an array of data names that it is dependent on. This enables the platform to track dependencies between components.
$exports : If a component puts data on the data bus, it should implement the $exports method, which should return an array of data names of teh datasets it places on the data bus.
$update : Whenever data on the data bus changes, the platform calls $imports on all components. For any component that imports the data that has changed on the bus, the $update method is called.
$select : The $select method is called when the component is selected by the user in the page. This gives the component the chance to highlight itself in the page as well as display any controls to edit the component. It should have an argument named "selected" that is passed to it. When the $select is not present, the component is not selectable.
$inline : The $inline method is used to control the buttons and controls that appear when a component is selected. (if the component has such controls). It should be passed a boolean argument named "open" that indicates whether to open or close the controls. In general, a component should open these controls whenever its $select method is called with selected set to true. However, ocassionally, the framework needs to hide the controls, so this method is made available for that purpose.

Component Effects


Adding a component to a blog or a workspace is easy, just by calling the $page.add method.

let config = $config(id);
if (!('wrappers' in config)) config.wrappers = [];
let params = {
	name: 'bounce',
	script: '/lib/effects/v1.0.0/bounce.js',
};
config.wrappers.push(params);
When a parameter such as the above is added to a configs wrappers, then when the component is instantiated, the script listed in the parameter is loaded and a function named "wrap" is called in the loaded script. The following is and example wrap function.

export function wrap(params, ctrl){

}
The parameter in the wrappers list is passed to the wrap function along with the instantiated component. The wrap function can alter the component in order to achieve its functionality. The primary way to do this is to replace the $process function on the component

Contents