# 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 ![image](https://hackmd.io/_uploads/SyW_lX3oye.png) * broadcast widget ```html <div class="input-box">Data:&nbsp; <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:&nbsp;&nbsp;<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" } ] } ```