Creating your first rail
What you will learn
In this lesson, you will discover a Dana vendor ready to use for common components of TV application. You will create a rail populated with datas coming from your VodService
.
Final visual result of this lesson will remain unchanged, but the buttons will be created dynamically based on data.
Add Dana components
To speed up development, Dana offers components for common TV design needs. You will find rail, grid, marquee… Here you will use RecyclingListView
to create a menu on top of your CatalogScreen
.
First of all, you need to install dependency to @dana/vendor-components
:
npm i --save-dev @dana/vendor-components
And add it to your profiles:
{
"base-css": {
"base": {
"name": "Css",
"vendors": [
"@dana/renderer-css",
"@dana/vendor-components",
"customBE"
]
}
},
"base-lightning": {
"base": {
"name": "Lightning HTML5",
"vendors": [
"@dana/renderer-lightning-html5",
"@dana/vendor-components",
"customBE"
]
}
}
}
Note
Do not forget to relaunch your npm start
to apply changes made in the profile.
Create a rail and set your button in it
In scripts/app/ui/views
, create a new file named MenuListView.js
. This class will inherit from RecyclingListView
. You need to define 2 properties:
- itemViewClass: the class to be used for each item of your list,
- itemMargin: the margin between each item of your list
RecyclingListView
will create as many child view necessary to display all datas. Scalability of this component is an advantage when creating list with a big number of elements. While navigating, children will be reused and new data will be set to change display.
In AppTheme
, add a SCREEN_HORIZONTAL_MARGIN
:
statics: {
SCREEN_HORIZONTAL_MARGIN: 50
}
New file content should be as follows :
import $RecyclingListView from "@RecyclingListView";
import $ButtonView from "@ButtonView";
import $Theme from "@Theme";
import $MHListNavigation from "@MHListNavigation";
import $MBindingRecycling from "@MBindingRecycling";
/**
* Display menu items
*
* @name MenuListView
* @class
* @extends RecyclingListView
* @property {MFixedRightNavigationType} navigationType Navigation type
* @property {ButtonView} itemViewClass Class used for item of the list
* @property {number} itemMargin Margin between items
*/
export default $RecyclingListView.declare("MenuListView", {
properties: /** @lends MenuListView.prototype */ {
itemViewClass: () => $ButtonView,
itemMargin: 20
},
style: {
height: $ButtonView.TEXT_HEIGHT + 2 * $ButtonView.VERTICAL_MARGIN,
width: $Theme.FULL_SCREEN_WIDTH - $Theme.SCREEN_HORIZONTAL_MARGIN * 2
}
});
Traits / Mixins overview
In object-oriented programming (OOP) languages, a mixin is a class that contains methods for use by other classes without having to be the parent class of those other classes. This allow to mutualize code and inject it in other classes. You can not use a mixin “as it”, it should be added to another class in any case. Dana supports this concept and multiple class are using it to add behaviour.
Caution
Even if mixin provides another way to mutualize code, simple inheritance should be preferred for every case of inheritance. Mixins are used for behaviour that needs to be be mutualized, like MFocusable
. Even if it is not forbidden, inheritance of mixins is discouraged because as it leads to bad maintainability.
For the list, you will use 3 mixins:
MHListNavigation
: used for horizontal navigationMBindingRecycling
: used to bind position of item to precedent item in the listMFixedRightNavigationType
: used to define navigation behaviour of the list (need to be defined as anavigationType
property)
Note
Mixins are prefixed with M
to be easily recognizable.
import $MFixedRightNavigationType from "@MFixedRightNavigationType";
export default $RecyclingListView.declare("MenuListView", {
traits: [$MHListNavigation, $MBindingRecycling],
properties: /** @lends MenuListView.prototype */ {
navigationType: () => $MFixedRightNavigationType
},
});
Caution
Keyword traits
allow you to declare mixins to be applied to the class.
Update ButtonView
To be usable in RecyclingListView
, class should inherit from RecyclingItemView
or use mixin MRecyclingItem
. It should also implement setData
method. It is responsible to use data of the item displaying the associated information. Here you will set the catalog name in your TextPrimitive
.
import $MRecyclingItem from "@MRecyclingItem";
export default $View.declare("ButtonView", {
traits: [$MRecyclingItem],
methods: /** @lends ButtonView.prototype */ {
setData: function (data) {
this.text.text = data.name;
}
},
});
Prepare CatalogScreen
As we are going to use the new child in the screen, start by cleaning it. Remove all mention of ButtonView
:
- remove import
- remove
button1
andbutton2
fromchildren
, - remove
button1
andbutton2
fromstyle
, - remove
left
andright
methods, - remove content of method
connectData
Now:
- import
MenuListView
, - add
MenuListView
inchildren
, - add style to place the menu properly on screen, in
style
, - retrieve data for menu by calling
getCatalogs
inprepareData
, - set data to the menu by calling
setData
inconnectData
import $MenuListView from "@MenuListView";
import $Theme from "@Theme";
xport default $AppScreen.declare("CatalogScreen", {
properties: {
vodService: {class: $VodService}
},
children: /** @lends CatalogScreen.prototype */ {
menu: {class: $MenuListView}
},
style: {
menu: {
x: $Theme.SCREEN_HORIZONTAL_MARGIN,
y: 20
}
},
methods: /** @lends CatalogScreen.prototype */ {
prepareData: function (context) {
return this.vodService.getCatalogs().then(data => {
return {
menu: data
};
});
},
connectData: function (context) {
this.menu.setData(this.data.menu);
}
}
});
Note
Result of prepareData
could be an object you created. It is useful when you need to retrieve multiple information.
You can launch your application and see that 2 buttons are displayed, and you can navigate between them using right and left key of your keyboard.
Summary
To summarize, during this lesson you have :
- used the component
RecyclingListView
, - discover mixins