Custom widgets: feature walkthrough

@ysc thank you.

Hi ,

i would create a custom widget an call this custom widget from another customer widget.
So I tried to setup a directive but the tpl html will be not loaded ? Can someone help ?
directive:

(function () {
    'use strict';
    angular      
    .module('app.widgets')
        .directive('shutter', function () {
            return {

                restrict: 'AE',
                scope: {
                    ngModel: '='
                },
                templateUrl: '/static/matrix-theme/shutter.html',
                controller: ['$controller', '$scope', function ($controller, $scope) {
                    debugger;
                    var myCtrl = $scope.ngModel;
                    return myCtrl;
                }],
                controllerAs: 'myCtrl',
            };
        })
        .config(function (WidgetsProvider) {
            debugger;
            WidgetsProvider.$get().registerType({
                type: 'shutter',
                displayName: 'Shutter',
                icon: 'download-alt',
                description: 'A button performing a certain action, like sending a command to an openHAB item'
            });
        });
});

Widget wich is calling the custom widget

<div oc-lazy-load="['/static/matrix-theme/shutter.js']">
                  	<shutter ng-model="rollershutter_1" ></shutter>
                  </div>
1 Like

Hi all,

I’m about to create a custom widget and im wondering if the following is possible, and if so… how?
If someone could help me or maybe find another way to get this working, that would be very much apprecciated.

I have the following code

<div>{{itemValue('Item_Name_1')}}</div>

and i have a config value named count as number

now i want to replace the 1 in the first code block with the config.count value.

thanks

<div>{{itemState('Item_Name_' + config.count.toString())}}</div>

should work.

1 Like

wow great! yes that works… Thank you very much :slight_smile:

this has been asked probably multiple times but i couldn’t find an answer… so i’ll give it a try:
are the codes for the “standard” widgets to be found somewhere? i’d like to modify the standard switch lightly but i don’t know where to begin…

thanks, but i’d like to start my custom widget on base of a standard widget and i have no idea how, just like @no.starm

You need to learn Angular JS (besides HTML and CSS):

1 Like

I know this is quite an old post and maybe things have changed but I try to accomplish the same with your code and it doesn’t work.
So far:
lightcontrol.html

<div class="row widget lightcontrol-widget" oc-lazy-load="['/static/habpanel.css']" style="width: 200px; height: 100px;">
    <div class="lightcontrol-title-row">
      <h3>{{getItem(config.dimmer).label}}</h3>
    </div>

    <div class="lightcontrol-body">
      <div class="lightcontrol-slider-container">
        <div ng-init="mySlider={
                        name: '',
                        item: config.dimmer,
                        floor: 0,
                        ceil: 100,
                        step: 1,
                        unit: '%'
                      }">
          <widget-slider ng-model="mySlider"/>
        </div>
      </div>

      <div class="lightcontrol-toggle-container" ng-init="switchItem = config.dimmer.replace('Dimmer', 'switch')">
        <label class="lightcontrol-switch">
          <input type="checkbox"
                 ng-checked="itemValue(switchItem) == 'ON'"
                 ng-click="sendCmd(switchItem, itemValue(switchItem) == 'OFF' ? 'ON' : 'OFF')" />
          <div class="lightcontrol-slider-toggle"></div>
        </label>
      </div>
    </div>
</div>

lightcontrol.js

angular
  .module('app.widgets')
  .directive('widgetLightcontrol', function() {
    return {
      restrict: 'E',
      scope: {
        ctrl: '='
      },
      templateUrl: '/static/lightcontrol.html',
      controllerAs: 'myCtrl',
      bindToController: true,
      controller: ['$scope', function($scope) {
        // Optional: you can access $scope.myCtrl.ctrl inside the template
      }]
    };
  });

Template widget:

<div oc-lazy-load="['/static/lightcontrol.js']">
  <div ng-repeat="dimmer in itemsInGroup('gDimmersToSwitches')">
  <widget-lightcontrol
    ctrl="{item: dimmer}">
  </widget-lightcontrol>
</div>

I can see the contours of my widget, that is all rendered fine, including the bottom border under the title, slider and toggle switch. But the items are not passed to the html-file so no values and such are loaded. I can’t see the title and the slider displays NaN%. If anyone can help me in this direction, please!

If that’s the name of your file, it won’t work because in your directive, you reference:

templateUrl: '/static/lightcontrol.html',

Good spot. I’ve double checked and I have made a typo in my post. Every reference and file is called lightcontrol. I’ll amend my post.

I think it has more to do with how ‘items’ are passed on. In my html, I have config.item while in the directive I use myCtrl and in the Template widget I use ctrl. It has to go wrong somewhere there but I’ve tried so many combination that one should have worked…

If you still have this setup @Mario_Aerni, could you please post your html file too? If your directive hasn’t changed, I should be able to figure it out I guess.

I’ve looked around in the forum but there aren’t many posts that talk about using a directive and certainly not in this way. So it would be very helpful to be able to analyse a working setup. ChatGPT wasn’t helpful either :wink:

Sure,
for example:
In Habpanel:

<div oc-lazy-load="[
                   '/static/matrix-theme/css/color-picker.min.css', 
                   '/static/matrix-theme/css/rzslider.css', 
                   '/static/matrix-theme/js/colorpicker-controller.js',
                   '/static/matrix-theme/js/color-picker.umd.min.js',
                   '/static/matrix-theme/js/rzslider.js']">
  <div class="section">
    <div class="controls">
      <div class="widget">
        <div class="icon off"><svg viewBox="0 0 48 48"><use xlink:href="/static/matrix-theme/icons/squidink.svg#drive-shelve"></use></svg></div>
        <div class="name">Devices</div>
        <div class="controlContainer">
          <div class="controlGroup" 
               ng-controller="CustomColorPickerController as colorCtrl">    
            <c-picker ng-init="colorCtrl.setColorItemName('Schlafzimmer_RGBW_Brightness', 
                																					 'Schlafzimmer_RGBW_Red',
                																					 'Schlafzimmer_RGBW_Green',
                																					 'Schlafzimmer_RGBW_Blue',
                																			 		 'Schlafzimmer_RGBW_White')" 
                      ctrl="colorCtrl">
            </c-picker>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

In colorpicker-controller.js:

angular
    .module('app.widgets.customcolorpickercontroller', ['color.picker.core'])
	.controller('CustomColorPickerController', CustomColorPickerController)
	.directive('cPicker', function() {
		return {
			restrict: 'E',
			scope: {
				ctrl: '='
			 },			
			templateUrl: '/static/matrix-theme/js/color-picker.html',
			controller: ['$controller', '$scope', function($controller, $scope) {
				var colorCtrl = $scope.ctrl;
				return colorCtrl;
			}],
			controllerAs: 'colorCtrl',			
		};
	});

if left the controller part, not needed for that example.

The content of the html file is irrelevant.

As you can see, c-picker is the tag, and declared as the directive. There’s nothing more to it.

Thanks for your code.

Could you explain why the code of the html file is irrelevant? It does get referenced… or is it a mandatory item in the controller structure?

I was hoping to input a groupItem and then iterate over its members and pass each member to my custom made widget. Somehow, I just can’t wrap my head around it. Whaaaaa. It’s driving me nuts ;(

Maybe leave it for a couple of day :slight_smile: