# Flexible TimePicker in TB
1. Create Time-Series type Widget
2. Add time display in HTML
```htmlmixed
<!-- an example -->
<div class="timestamp">From {{timeStart}} to {{timeEnd}}</div>
```
3. Use `self.ctx
.timeWindow.maxTime` and `self.ctx
.timeWindow.minTime` to get timeWindow data
```javascript
self.onInit = function() {
self.ctx.$scope.timeEnd = transferToDate(self.ctx
.timeWindow.maxTime);
self.ctx.$scope.timeStart = transferToDate(self.ctx
.timeWindow.minTime);
}
self.onDataUpdated = function() {
self.ctx.$scope.timeEnd = transferToDate(self.ctx
.timeWindow.maxTime);
self.ctx.$scope.timeStart = transferToDate(self.ctx
.timeWindow.minTime);
}
function transferToDate(timestamp) {
var dd = new Date(timestamp);
const month = dd.getMonth() + 1;
const day = dd.getDate();
let hour = dd.getHours();
let min = dd.getMinutes();
hour = timeZeroCheck(hour);
min = timeZeroCheck(min);
const date = month + '/' + day + ' ' + hour + ':' + min;
return date;
}
function timeZeroCheck(num){
num = num.toString();
if(num.length === 1){
num = '0'+ num;
}
return num;
}
```
4. Add an action to handle time select and change
* Method1

```html
<!-- dialogHTML -->
<div class="container" style="background: #000000; color: #ffffff;
padding: 24px 24px 12px; width: 280px;">
<div class="box" style="margin-bottom: 12px; display: flex; justify-content: space-between;">
<label for="start">Start Date:</label>
<input type="date" id="start" name="trip-start" />
</div>
<div class="box" style="margin-bottom: 12px; display: flex; justify-content: space-between;">
<label for="start-time">Start Time:</label>
<input type="time" id="start-time" name="appt" required />
</div>
<div class="box" style="margin-bottom: 12px; display: flex; justify-content: space-between;">
<label for="end">End Date:</label>
<input type="date" id="end" name="end" />
</div>
<div class="box" style="margin-bottom: 12px; display: flex; justify-content: space-between;">
<label for="end-time">End Time:</label>
<input type="time" id="end-time" name="end-time"
required />
</div>
<div class="btn-wrap" style="display: flex; justify-content: center;">
<button mat-flat-button (click)="cancel()" style="margin: 12px 4px;">Cancel</button>
<button mat-stroked-button (click)="save()" style="background: #9c5f5f; color: #ffffff; margin: 12px 4px;">Confirm</button>
</div>
</div>
```
:::success
Use `widgetContext.dashboard
.dashboardTimewindowChangedSubject.next(
newDashboardtimewindow);` to update timeWindow data
:::
```javascript
let $injector = widgetContext.$scope.$injector;
let customDialog = $injector.get(widgetContext.servicesMap
.get('customDialog'));
openDialog();
function openDialog() {
customDialog.customDialog(dialogHTML,
dialogController).subscribe();
}
function dialogController(instance) {
let vm = instance;
vm.cancel = function() {
vm.dialogRef.close(null);
};
vm.save = function() {
const start = getTargetValue(`start`) + 'T' + getTargetValue(`start-time`) +'+0800';
const end = getTargetValue(`end`) + 'T' + getTargetValue(`end-time`) +'+0800';
const startTime = Date.parse(start);
const endTime = Date.parse(end);
updateTimeWindow(startTime, endTime);
var date1 = new Date(startTime);
vm.dialogRef.close(null);
};
function getTargetValue(name) {
const newValue = document.querySelector(`#${name}`)
.value;
return newValue;
}
function updateTimeWindow(startTime, endTime) {
const newDashboardtimewindow = {
aggregation: {
limit: 25000,
type: "NONE"
},
hideAggInterval: false,
hideAggregation: false,
hideInterval: false,
history: {
historyType: 1,
fixedTimewindow: {
startTimeMs: startTime,
endTimeMs: endTime,
}
},
selectedTab: 1
};
widgetContext.dashboard
.dashboardTimewindowChangedSubject.next(
newDashboardtimewindow);
}
}
```
* A simple example to select time

<br/>
* Method2 (suggest)
Write in the widgets library
```javascript
self.onInit = function() {
self.ctx.$scope.timeEnd = transferToDate(self.ctx
.timeWindow.maxTime);
self.ctx.$scope.timeStart = transferToDate(self.ctx
.timeWindow.minTime);
//for timePicker dialog
self.ctx.$scope.openDialog = openDialog;
const $injector = self.ctx.$scope.$injector;
const customDialog = $injector.get(self.ctx
.servicesMap
.get(
'customDialog'));
function openDialog() {
customDialog.customDialog(dialogHTML,
dialogController).subscribe();
}
function dialogController(instance) {
let vm = instance;
vm.cancel = function() {
vm.dialogRef.close(null);
};
vm.save = function() {
const start = getTargetValue(`start`) +
'T' + getTargetValue(`start-time`) +
'+0800';
const end = getTargetValue(`end`) +
'T' + getTargetValue(`end-time`) +
'+0800';
const startTime = Date.parse(start);
const endTime = Date.parse(end);
updateTimeWindow(startTime, endTime);
var date1 = new Date(startTime);
vm.dialogRef.close(null);
};
function getTargetValue(name) {
const newValue = document.querySelector(
`#${name}`)
.value;
return newValue;
}
function updateTimeWindow(startTime, endTime) {
const newDashboardtimewindow = {
aggregation: {
limit: 25000,
type: "NONE"
},
hideAggInterval: false,
hideAggregation: false,
hideInterval: false,
history: {
historyType: 1,
fixedTimewindow: {
startTimeMs: startTime,
endTimeMs: endTime,
}
},
selectedTab: 1
};
self.ctx.dashboard
.dashboardTimewindowChangedSubject.next(
newDashboardtimewindow);
}
}
}
self.onDataUpdated = function() {
self.ctx.$scope.timeEnd = transferToDate(self.ctx
.timeWindow.maxTime);
self.ctx.$scope.timeStart = transferToDate(self.ctx
.timeWindow.minTime);
}
function transferToDate(timestamp) {
var dd = new Date(timestamp);
const month = dd.getMonth() + 1;
const day = dd.getDate();
let hour = dd.getHours();
let min = dd.getMinutes();
hour = timeZeroCheck(hour);
min = timeZeroCheck(min);
const date = month + '/' + day + ' ' + hour + ':' + min;
return date;
}
function timeZeroCheck(num) {
num = num.toString();
if (num.length === 1) {
num = '0' + num;
}
return num;
}
```