# Advanced Widgets Development in ThingsBoard
>[!Note]
>Provide simple examples demonstrating advanced widget features.
[toc]
## HTTP Service
* Use Angular httpClient
* Include ThingsBoard access token
```javascript
self.ctx.http.get(url)
.subscribe(
(res) => {
console.log(res);
},
(err) => {
alert(
`Error Status ${err.status}. ${err.error.message}`
);
});
```
## Broadcast Service

* broadcast widget
```html
<div class="input-box">Data:
<input type="text" name="txt" id="txt" [(ngModel)]="inputTxt" />
</div>
<div class="btn" (click)="transferTxt()">Click to transfer data</div>
```
```javascript
self.onInit = function() {
let $scope = self.ctx.$scope;
$scope.inputTxt = '123';
self.ctx.broadcastService = $scope.$injector.get(self.ctx.servicesMap.get('broadcastService'));
$scope.transferTxt = transferTxt;
function transferTxt() {
self.ctx.broadcastService.broadcast('TEXT', $scope.inputTxt);
}
}
```
* subscribe widget
```htmlembedded
<div>{{ widgetText }}</div>
```
```javascript
self.onInit = function() {
let $scope = self.ctx.$scope;
$scope.widgetText = 'Please click button in the left widget.';
self.ctx.broadcastService = $scope.$injector.get(self.ctx.servicesMap.get('broadcastService'));
self.ctx.broadcastService.on('TEXT', (event, args) => {
$scope.widgetText = args[0];
self.ctx.detectChanges();
});
}
```
## Custom timeWindow
* ==Time-Series== Widget Only
* Start Time: `self.ctx.timeWindow.minTime` (millisecond)
* End Time: `self.ctx.timeWindow.maxTime` (millisecond)
* Time Zone: `self.ctx.timeWindow.timezone`
```javascript
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);
}
```
### Subscribe dashboard timeWindow change
```javascript
self.onInit = function() {
self.ctx.$scope.timeSubscribe = self.ctx.dashboard.dashboardTimewindowChanged;
self.ctx.$scope.timeSubscribe.subscribe(
(timewindow) => {
console.log(
'dashboard timewindow changed!')
console.log(timewindow);
}
);
};
self.onDestroy = function() {
self.ctx.$scope.timeSubscribe.unsubscribe();
}
```
## Custom Dialog
```htmlmixed
<button (click)="openDialog()">Open a dialog</button>
```
```javascript
self.onInit = function() {
self.ctx.$scope.openDialog = openDialog;
const $injector = self.ctx.$scope.$injector;
const customDialog = $injector.get(self.ctx.servicesMap.get('customDialog'));
function openDialog() {
customDialog.customDialog(htmlTemplate,
dialogController).subscribe();
}
var htmlTemplate = `
<div class="dialog-container" style="width: 200px; height: 150px; padding: 24px 12px; position: relative;">
<h5 style="text-align: center; font-size: 16px; font-weight: 550; margin-bottom: 24px; color: #584e4e;">Custom Dialog</h5>
<div class="wrap" style="display: flex; justify-content: center; align-items: center;">
<div>Hello World</div>
</div>
<span (click)="cancel()" class="material-icons" style="cursor: pointer; position: absolute; top: 4px; right: 4px; color: #584e4e;">close</span>
</div>
`;
function dialogController(instance) {
let ct = instance;
ct.cancel = function() {
ct.dialogRef.close(null);
};
}
}
```
## Navigation
* Use `self.ctx.stateController.openState(id: string, params?: StateParams, openRightLayout?: boolean);`
-> navigate to another page (dashboard state)
```javascript
self.ctx.stateController.openState('dashboard_state_id', {}, false);
```
## Dashboard State in Widget (State in State)
* Dashboard states can be put inside a widget.
```html
<!-- Custom Widget -->
<tb-dashboard-state [ctx]="ctx"
stateId="dashboard_state_id"
class="dashboard-state">
</tb-dashboard-state>
```
## Settings Schema
```htmlembedded
<div class="box-wrap">
<div>Show text: <span style="color: blue;">{{ text }}</span></div>
<div class="box box1" style="background: {{box1Color}};">Box1</div>
<div class="box box2" style="background: {{box2Color}};">Box2</div>
</div>
```
```javascript
self.onInit = function() {
const settings = self.ctx.settings;
self.ctx.$scope.text = settings.text || "text";
self.ctx.$scope.box1Color = settings.box1Color || '#e89623';
self.ctx.$scope.box2Color = settings.box2Color || '#8FC0DA';
}
```
```json
//Settings Schema
{
"schema": {
"type": "object",
"title": "Settings",
"properties": {
"text": {
"title": "text",
"type": "string",
"default": "text"
},
"box1Color": {
"title": "Box1 Color",
"type": "string",
"default": "#e89623"
},
"box2Color": {
"title": "Box2 Color",
"type": "string",
"default": "#8FC0DA"
}
}
},
"form": [
"text",
{
"key": "box1Color",
"type": "color"
},
{
"key": "box2Color",
"type": "color"
}
]
}
```