TaskEditor
Provides a UI to edit tasks in a popup dialog. It is implemented as a Tab Panel with several preconfigured built-in tabs. Although the default configuration may be adequate in many cases, the Task Editor is easily configurable.
This demo shows how to use TaskEditor as a standalone widget:
//<code-header>
fiddle.title = 'Task editor';
//</code-header>
const project = new ProjectModel({
startDate : new Date(2020, 0, 1),
events : [
{
id : 1,
name : 'Write docs',
expanded : true,
children : [
{ id : 2, name : 'Proof-read docs', startDate : '2020-01-02', endDate : '2020-01-05', effort : 0 },
{ id : 3, name : 'Release docs', startDate : '2020-01-09', endDate : '2020-01-10', effort : 0 }
]
}
],
dependencies : [
{ id : 1, fromEvent : 2, toEvent : 3 }
]
});
const taskEditor = new TaskEditor({
rootElement : document.body,
listeners : {
save : () => taskEditor.hide()
}
});
const button = new Button({
appendTo : targetElement,
text : 'Show TaskEditor',
onClick : () => {
taskEditor.loadEvent(project.eventStore.getById(2));
taskEditor.showBy({
target : button.element,
align : 'l-r',
offset : 5
});
}
});To hide built-in tabs or to add custom tabs, or to append widgets to any of the built-in tabs use the items config.
The Task editor contains tabs by default. Each tab is a container with built-in widgets: text fields, grids, etc.
| Tab ref | Text | Weight | Description |
|---|---|---|---|
generalTab |
General | 100 | Name, start/end dates, duration, percent done, effort |
predecessorsTab |
Predecessors | 200 | Grid with incoming dependencies |
successorsTab |
Successors | 300 | Grid with outgoing dependencies |
resourcesTab |
Resources | 400 | Grid with assigned resources |
advancedTab |
Advanced | 500 | Assigned calendar, scheduling mode, constraints, etc |
notesTab |
Notes | 600 | Text area to add notes to the selected task |
Task editor customization example
This example shows a custom Task Editor configuration. The built-in "Notes" tab is hidden, a custom "Files" tab is added, the "General" tab is renamed to "Common" and "Custom" field is appended to it. Double-click on a task bar to start editing:
//<code-header>
fiddle.title = 'Custom task edit';
//</code-header>
const project = new ProjectModel({
startDate : new Date(2017, 0, 1),
tasks : [
{
id : 1,
name : 'Write docs',
expanded : true,
custom : 'Parent custom field value',
children : [
// 'custom' field is auto exposed to Task model, then its name is used in TaskEditor to get/set values
{
id : 2,
name : 'Proof-read docs',
startDate : '2017-01-02',
endDate : '2017-01-05',
custom : 'Proof-read custom value'
},
{
id : 3,
name : 'Release docs',
startDate : '2017-01-09',
endDate : '2017-01-10',
custom : 'Release custom value'
}
]
}
],
dependencies : [
{ id : 1, fromTask : 2, toTask : 3 }
]
});
// May be registered in case this example is run again
if (!Widget.factoryable.registry.custom_filestab) {
// Custom FilesTab class (the last item of tabsConfig)
class FilesTab extends Grid {
// Factoryable type name
static get type() {
return 'custom_filestab';
}
static configurable = {
title : 'Files',
defaults : {
labelWidth : 200
},
columns : [{
text : 'Files attached to task',
field : 'name',
type : 'template',
template : data => `<i class="fa fa-fw fa-${data.record.data.icon}"></i>${data.record.data.name}`
}]
};
loadEvent(eventRecord) {
let files = [];
// prepare dummy files data
switch (eventRecord.data.id) {
case 1:
files = [
{ id : 1, name : 'Image1.png', icon : 'image' },
{ id : 2, name : 'Chart2.pdf', icon : 'chart-pie' },
{ id : 3, name : 'Spreadsheet3.pdf', icon : 'file-excel' },
{ id : 4, name : 'Document4.pdf', icon : 'file-word' },
{ id : 5, name : 'Report5.pdf', icon : 'user-chart' }
];
break;
case 2:
files = [
{ id : 1, name : 'Chart11.pdf', icon : 'chart-pie' },
{ id : 2, name : 'Spreadsheet13.pdf', icon : 'file-excel' },
{ id : 3, name : 'Document14.pdf', icon : 'file-word' }
];
break;
case 3:
files = [
{ id : 1, name : 'Image21.png', icon : 'image' },
{ id : 2, name : 'Spreadsheet23.pdf', icon : 'file-excel' },
{ id : 3, name : 'Document24.pdf', icon : 'file-word' },
{ id : 4, name : 'Report25.pdf', icon : 'user-chart' }
];
break;
} // eo switch
this.store.data = files;
} // eo function loadEvent
} // eo class FilesTab
// register 'filestab' type with its Factory
FilesTab.initClass();
}
const gantt = new Gantt({
appendTo : targetElement,
flex : '1 0 100%',
height : 200,
project, // Gantt needs project to get schedule data from
startDate : new Date(2016, 11, 31),
endDate : new Date(2017, 0, 11),
columns : [
{ type : 'name', field : 'name', text : 'Name' }
],
features : {
taskEdit : {
items : {
generalTab : {
// Change title of General tab
title : 'Common',
items : {
// Add new field
newCustomField : {
type : 'textfield',
weight : 710,
label : 'Custom (New Field)',
name : 'custom' // Name of the field matches data field name, so value is loaded/saved automatically
}
}
},
// Remove Notes tab
notesTab : false,
// Add custom Files tab to the second position
filesTab : {
type : 'custom_filestab',
weight : 110
}
},
editorConfig : {
// Custom height of the Task Editor
height : '35em'
}
} // eo taskEdit
} // eo features
});Custom fields in the Task Editor work only if the field is explicitly defined in the Task model. When defined,
the field can be added, updated, and stored in the TaskStore, even if it is not present in the initial task data.
Bryntum extracts fields only from the first task record when no definitions are provided, which can lead to
inconsistent behavior. Always define custom fields in the Task model to ensure predictable
and reliable functionality.
export default class CustomTaskModel extends TaskModel {
static fields = [
{ name: 'custom', type: 'string' }
];
}
const project = new ProjectModel({
taskModelClass : CustomTaskModel,
})
Configs
124
Configs
124Common
Content
CSS
DOM
Float & align
Layout
misc
Misc
Other
Scrolling
Properties
101
Properties
101Class hierarchy
Identifies an object as an instance of SchedulerTaskEditor class, or subclass thereof