Customizing task contents
This guide describes how to customize the contents of task cards on the TaskBoard.
Configuring task items
Cards are divided into three parts: header, body and footer. The contents of those can be somewhat customized by configuring which task items to show in which part. Each part has a corresponding config that accepts task items. The configs are:
- headerItems - Defaults to use a text item (named
text) displaying the name of a task. - bodyItems - Defaults to use a text item (named
text) displaying the description of a task. - footerItems - Defaults to use a resource avatar item (named
resourceAvatars), if resources are used in the app.
The following item types are available:
- image - Displays an image
- progress - Displays a progress bar
- rating - Displays a star rating
- resourceAvatars - Displays resource avatars or initials
- separator - Displays a separator (
<hr>) - tags - Displays tags, from a string, array of strings or array of objects
- template - Displays content from a template
- text - Displays text
- todoList - Displays todo items with checkboxes
Given the following data:
{
"id" : 1,
"name" : "Write a guide",
"title" : "Customizing task contents",
"description" : "On customizing task contents",
"summary" : "Guide that shows the different options",
"prio" : "high",
"status" : "doing",
"percentDone" : 40
}
By default we get the following card rendition:
//<code-header>
fiddle.title = 'Default task contents';
//</code-header>
const taskBoard = new TaskBoard({
appendTo : targetElement,
features : {
columnToolbars : false
},
// Columns to display
columns : [
'todo',
'doing',
'done'
],
// Field used to pair a task to a column
columnField : 'status',
// Project using inline data
project : {
tasks : [
{
id : 1,
name : 'Write a guide',
title : 'Customizing task contents',
description : 'On customizing task contents',
summary : 'Guide that shows the different options',
prio : 'high',
status : 'doing'
}
]
}
});Here we reconfigure and add some items:
const taskBoard = new TaskBoard({
headerItems : {
// Reconfigure the default text item
text : { field : 'title' }
},
bodyItems : {
// Reconfigure the default text item
text : { field : 'summary' },
// Add a new progress item to the body
// (no field is supplied => key is used as the field = percentDone)
percentDone : { type : 'progress' }
},
footerItems : {
// Add a new text item to the footer
prio : { type : 'text' }
}
})
Which results in:
//<code-header>
fiddle.title = 'Task content fields';
//</code-header>
const taskBoard = new TaskBoard({
appendTo : targetElement,
headerItems : {
text : { field : 'title' }
},
bodyItems : {
text : { field : 'summary' },
percentDone : { type : 'progress' }
},
footerItems : {
prio : { type : 'text' }
},
features : {
columnToolbars : false
},
// Columns to display
columns : [
'todo',
'doing',
'done'
],
// Field used to pair a task to a column
columnField : 'status',
// Project using inline data
project : {
tasks : [
{
id : 1,
name : 'Write a guide',
title : 'Customizing task contents',
description : 'On customizing task contents',
summary : 'Guide that shows the different options',
prio : 'high',
status : 'doing',
percentDone : 40,
eventColor : 'blue'
}
]
}
});Customizing card elements using a taskRenderer
TaskBoard can be configured with a taskRenderer, a function called for each task when its card is about to be drawn. In this function you can manipulate a DOM config object and by doing so affect what ends up in the DOM.
Configuring a simple taskRenderer:
const taskBoard = new TaskBoard({
taskRenderer({ taskRecord, cardConfig }) {
// Add an icon to the header of each card
cardConfig.children.header.children.icon = {
tag : 'i',
class : 'fa fa-coffee',
style : 'order : 200'
}
}
});
Result:
//<code-header>
fiddle.title = 'Task renderer';
//</code-header>
const taskBoard = new TaskBoard({
appendTo : targetElement,
taskRenderer({ taskRecord, cardConfig }) {
// Add an icon to the header of each card
cardConfig.children.header.children.icon = {
tag : 'i',
class : 'fa fa-coffee',
style : 'order : 200'
};
},
features : {
columnToolbars : false
},
// Columns to display
columns : [
'todo',
'doing',
'done'
],
// Field used to pair a task to a column
columnField : 'status',
// Project using inline data
project : {
tasks : [
{
id : 1,
name : 'Write a guide',
description : 'On customizing task contents',
prio : 'high',
status : 'doing',
eventColor : 'yellow'
},
{
id : 2,
name : 'Make demos',
description : 'For the guide',
prio : 'medium',
status : 'todo',
eventColor : 'blue'
}
]
}
});As shown by the snippet above, a taskRenderer is called with a single argument with taskRecord and cardConfig
properties. By manipulating cardConfig you affect the resulting DOM. It is a pretty complex object, which gives you
access to the cards full markup.
The cardConfig object
This listing shows the relevant parts of the cardConfig object before the modification above (with comments inserted):
cardConfig = {
// CSS classes applied to the cards outermost element (the card itself).
// Uses object form to simplify adding conditional classes
class : {
'b-task-board-card' : true
},
// Child elements = the cards different parts: header, body, footer
// Uses object form to simplify accessing a specific part of the card (children.body vs children[1])
children : {
// Card header
header : {
class : 'b-task-board-card-header',
children : {
// Header has a single child by default, holding its text
text : {
class : {
'b-task-board-task-item' : 1,
'b-task-board-text' : 1
},
text : 'Make demos'
},
// The modification in the taskRenderer snippet above inserts the icon here, ending up as:
// icon : {
// tag : 'i',
// class : 'fa fa-coffee',
// style : 'order : 200'
// }
}
},
// Card body
body : {
class : 'b-task-board-card-body',
children : {
// Body has a single child by defauly, holding its text
text : {
class : {
'b-task-board-task-item' : 1,
'b-task-board-text' : 1
},
text : 'For the guide'
}
}
},
// Card footer (empty by default, empty parts are removed before rendering to the DOM)
footer : {
class : 'b-task-board-card-footer',
children : {}
}
}
}
The cardConfig above (with the icon added) ends up as the following HTML (slightly redacted to save some space):
<div class="b-task-board-card">
<header class="b-task-board-card-header">
<div class="b-task-board-task-item b-task-board-text">Make demos</div>
<i class="fa fa-coffee"></i>
</header>
<section class="b-task-board-card-body">
<div class="b-task-board-task-item b-task-board-text">For the guide</div>
</section>
</div>
It might seem complicated to use the DomConfig object form over a string template, but it is for good reasons:
- It is easier to manipulate an object than a string, allowing for easier customization
- It is faster to parse than a string
Customization examples
Some things you might want to do, and how to do it:
Add a CSS class to the card:
cardConfig.class.myCssClass = true;
Change the headers text:
cardConfig.children.header.children.text.text = 'Header text';
Add an image to the body:
cardConfig.children.body.children.image = {
tag : 'img',
src : 'myimage.png'
};