Template widget - passing string variable

So i am trying to reuse so code across two separate dashboards. The code is loaded in to a template widget via ng include as below:

<div ng-include="'/static/HabPanelTemplate/Tablet_Den_Switches.html'"></div>
<div ng-include="'/static/HabPanelTemplate/Tablet_Camera_Divs.html'"></div>

What i would like to do is be able in Tablet_Den_Switches.html’

to have a line like

<div ng-init="CameraViewIf='DenCameraView'"></div>

so that i can reuse Tablet_Camera_Divs.htm

and code it something like:

<div ng-if="itemValue(CameraViewIf)=='CameraKioskView'">
<div style="height: 800px">
  <div uib-carousel active="0" interval="5000" no-wrap="false">
    <div uib-slide index="0" ng-init="model1 = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=2&scale=100&maxfps=15&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
      <widget-image ng-model="model1" style="margin:auto;"/>
    </div>
    <div uib-slide index="1" ng-init="model2 = { 'url':'http:/CameraViewIf/192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=3&scale=100&maxfps=15&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
      <widget-image ng-model="model2" style="margin:auto;"/>
    </div>
      <div uib-slide index="2" ng-init="model3 = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=4&scale=100&maxfps=15&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
      <widget-image ng-model="model3" style="margin:auto;"/>
    </div>
      <div uib-slide index="3" ng-init="model4 = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=5&scale=100&maxfps=15&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
      <widget-image ng-model="model4" style="margin:auto;"/>
    </div>
    <div uib-slide index="4" ng-init="model5 = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=6&scale=100&maxfps=12&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
     <widget-image ng-model="model5" style="margin:auto;"/>
    </div>
  </div>
</div>
</div>

There are multiple ng-ifs in this file and i would like to use it on different dashboards but there would be a different item to evaluate in the ng-if and i would rather not have to repeat all this code for when i want to make changes (add or remove cameras etc,) The above does not work. Ideas?

here is our it is currently hard coded and working (added second div to show that multiple ng-ifs re in play here)

<div ng-if="itemValue('DenCameraView')=='CameraKioskView'">
<div style="height: 800px">
  <div uib-carousel active="0" interval="5000" no-wrap="false">
    <div uib-slide index="0" ng-init="model1 = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=2&scale=100&maxfps=15&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
      <widget-image ng-model="model1" style="margin:auto;"/>
    </div>
    <div uib-slide index="1" ng-init="model2 = { 'url':'http:/CameraViewIf/192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=3&scale=100&maxfps=15&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
      <widget-image ng-model="model2" style="margin:auto;"/>
    </div>
      <div uib-slide index="2" ng-init="model3 = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=4&scale=100&maxfps=15&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
      <widget-image ng-model="model3" style="margin:auto;"/>
    </div>
      <div uib-slide index="3" ng-init="model4 = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=5&scale=100&maxfps=15&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
      <widget-image ng-model="model4" style="margin:auto;"/>
    </div>
    <div uib-slide index="4" ng-init="model5 = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=6&scale=100&maxfps=12&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
     <widget-image ng-model="model5" style="margin:auto;"/>
    </div>
  </div>
</div>
</div>
  
<div ng-if="itemValue('DenCameraView')=='TabletFrontDoorOpen'">
<div style="height: 800px">
  
    <div ng-init="frontDoor = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=2&scale=100&maxfps=15&buffer=1000&user=volfan6415&pass=Pippi1959', 'refresh': 1 }">
      <widget-image ng-model="frontDoor" style="margin:auto;"/>
    </div>
    
  
</div>

Sounds like this could be handled by a custom widget with a config parameter instead of doing it with templates.

So i was able to get it to work by moving:

<div ng-init="CameraViewIf='DenCameraView'"></div>

into the Template window itself so that it was on the same level as the ng-includes. My suspicion is that there must have been something weird going on with how the ng-include was loading everything.

So now my Tablet_Camera_Divs.html looks like above. And the code in the template widget looks like

<div ng-init="CameraViewIf='DenCameraView'"></div>
<div ng-include="'/static/HabPanelTemplate/Tablet_Den_Switches.html'"></div>
<div ng-include="'/static/HabPanelTemplate/Tablet_Camera_Divs.html'"></div>

And everything is working.

Admittedly i do not have experience creating my own custom widgets but this is problem something that i should look into as i guess this would give me cleaner access to what i am ultimately trying to achieve.

I am certainly open to suggestions here on how to code these better.

So i have two tablets. One in the kitchen and one in the den running fully kiosk browser. They can send a motion event via mqtt. When the motion event is sent a rule processes the vent and updates a string item specific to the tablet ( i.e.“DenCameraView”). This way the code which is contained in ‘/static/HabPanelTemplate/Tablet_Den_Switches.html’ and is behind a ng-ig (

) turns on and displays the switches. Then 30 seconds later the motion event times out via the expire binding and same rule reactivates the DenCameraView item so that it now equals CameraKioskView and the switches go away and the security cameras can start scrolling again. I also have several other events in there like when the front door opens, swich to the living room camera, if there is too much noise in the nursery turn that camera on etc…

here is the rule file

JSRule({
    name: "Den Tablet Switch Displays",
    description: "Update Den Switch Displays",
    triggers: [
        ItemStateChangeTrigger("Knoxwebcameview","OFF","ON"),
        ItemStateChangeTrigger("DenDisplaySwitches","OFF","ON"),
        ItemStateChangeTrigger("CameraKioskView","ON","OFF"),
        ItemStateChangeTrigger("TabletFrontDoorOpen","OFF","ON"),
        ItemStateChangeTrigger("TabletDoorBellRung","OFF","ON"),
        ItemStateChangeTrigger("KitchenDisplaySwitches","OFF","ON")

    ],
    execute: function( module, input){
        var event = getTriggeredData(input);
        var triggeringItem = event.itemName.toString();
        if (!(triggeringItem.equals("CameraKioskView"))){
        sendCommand("CameraKioskView", "ON");}
    
            if (!(triggeringItem.equals("KitchenDisplaySwitches"))){
                sendCommand("DenCameraView",triggeringItem);
            }
            if (!(triggeringItem.equals("DenDisplaySwitches"))){
                sendCommand("KitchenCameraView",triggeringItem);
            }
        }
    });

Then on the right panel there is also a template widget that displays the time and information about that rooms temperature and alarm status, unless either the whole home audio is playing or Emby is playing a movie. In that case the poster for the playing movie or playing song is also displayed in place of the alarm info and temp info.

Here are the rules files and template files which make the right panel work ( i am still working on transitioning these to .html files)

Right template.html

<div ng-init="topClock={'name': 'Top_Clock',
					'mode': 'Digital\n\t\t    ',
                    'digital_format': 'EEE M/d/yy',
                    'font_size': '20'}"></div>

<div ng-init="modelPoster={'item': 'Den_Poster_URL',
                    'image_source': 'item-string',
                    'refresh': 5,
                    'intervaltype': 'seconds',
                    'background': 'transparent'}"></div>

<div ng-init="bottomClock={'name': 'Bottom_Clock',
					 'mode': 'Digital\n\t\t    ',
                    'digital_format': 'h:mm a',
                    'font_size': '38'}"></div>
<div ng-init="temperature={ 'name': tempItem.name, 'item': tempItem.item,
                    'type': 'dummy',
                    'useserverformat': true,
                    'font_size': '24' }"></div>
  
<div ng-init="alarmStatus={ 'name': 'Alarm Status', 'item': 'Senser_Icon_Display',
                    'type': 'dummy',
                    'useserverformat': false,
                    'font_size': '24' }"></div>

<widget-clock ng-model="topClock"></widget-clock>
                    


<div ng-if="itemValue('Tablet_Display_Poster')=='ON'">


  <widget-image ng-model="modelPoster"></widget-image>
</div>
  

  <widget-clock ng-model="bottomClock"></widget-clock>


<div ng-if="itemValue('Tablet_Display_Poster')=='OFF'">
  
  	
    	
    	<widget-dummy ng-model="temperature" style="color:#bec3bb;"></widget-dummy>
		
  
  
    <widget-dummy ng-model="alarmStatus" style="color:#bec3bb;"></widget-dummy>
</div>

Tablet poster rule

JSRule({
    name: "update images to display on tablets",
    description: "Send update state command to all sonoffs",
    triggers: [
        ItemStateUpdateTrigger("EMBYPosterImage_URL"),
        ItemStateUpdateTrigger("Echo_Stereo_ImageUrl"),
        ItemStateChangeTrigger("Display_ECHO_Poster")
		//CommandEventTrigger("AC_Test", "OFF")
    ],
    execute: function( module, input){
        var emby = getItem("Display_EMBY_Poster").state.toString();
        var echo = getItem("Display_ECHO_Poster").state.toString();
        var embyurl = getItem("EMBYPosterImage_URL").state.toString();
        var echourl = getItem("Echo_Stereo_ImageUrl").state.toString();
            if (emby.equals("ON") && echo.equals("OFF")){
                sendCommand("Tablet_Display_Poster",ON);
                sendCommand("Den_Poster_URL",embyurl);
                sendCommand("Kitchen_Poster_URL",embyurl);

            } else if (emby.equals("OFF") && echo.equals("ON")){
                sendCommand("Tablet_Display_Poster",ON);
                sendCommand("Den_Poster_URL",echourl);
                sendCommand("Kitchen_Poster_URL",echourl);

            } else if ((emby.equals("ON") && echo.equals("ON"))){
                sendCommand("Tablet_Display_Poster",ON);
                sendCommand("Kitchen_Poster_URL",echourl);
                sendCommand("Den_Poster_URL",embyurl);
            } else if (emby.equals("OFF") && echo.equals("OFF")){
                sendCommand("Tablet_Display_Poster",OFF);
                sendCommand("Kitchen_Poster_URL","");
                sendCommand("Den_Poster_URL","");
            }
            else{
                sendCommand("Tablet_Display_Poster",OFF);
                sendCommand("Kitchen_Poster_URL","");
                sendCommand("Den_Poster_URL","");
            }
    }
});

And some images of it in action

security cameras rolling

the switch view

with media playing

The purpose of custom widgets is actually to be able to share the same template and add configuration parameters that you can use in code, and set up individually for each instance of the widget.

In your case you would have all your view alternatives in the custom widget and define the String item which controls the view for that tablet using a config parameter instead of doing it with ng-init. From the home page click on Panel settings, then Manage (custom widgets), add a new one, go to the Settings tab and add a parameter of type Item with e.g. view_item as the ID, then in the Code tab you can define all your view alternatives – btw you can use ngSwitch:

<div ng-switch="itemState(config.view_item)">
    <div ng-switch-when="CameraKioskView">
        ...
    </div>
    <div ng-switch-when="TabletFrontDoorOpen">
        ...
    </div>
    ...
    <div ng-switch-default>
       <!-- default view -->
    </div>
</div>

Note that should be able the view in external “ng_included” templates if you prefer.
You can click on the Preview tab and configure the parameter with the gears icon while you’re working on it. When done save the widget and then you’ll be able to use it when designing your dashboards (one per tablet I presume) and configure the view_item individually.

Thank you @ysc for the tip on the custom widget. Should have looked into this sooner. I guess i never really fully understood how they worked. So much easier that way. I have the screen working as one widget now. Still using an ngInclude for the two button panel html files. though. It works flawlessly. Thank you so much!

<div ng-init="knoxRoom = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=3&scale=100&maxfps=15&buffer=1000&user=XXXXXX&pass=XXXXXXX', 'refresh': 1 }"></div>
<div ng-init="livRoom = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=2&scale=100&maxfps=15&buffer=1000&user=XXXXXXX&pass=XXXXXXX', 'refresh': 1 }"></div>
<div ng-init="outside = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=6&scale=100&maxfps=12&buffer=1000&user=XXXXXXX&pass=XXXXXXXX', 'refresh': 1 }"></div>
<div ng-init="neveRoom = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=5&scale=100&maxfps=15&buffer=1000&user=XXXXXXX&pass=xxxxxxxx', 'refresh': 1 }"></div>
<div ng-init="topClock={'name': 'Top_Clock',
					'mode': 'Digital\n\t\t    ',
                    'digital_format': 'EEE M/d/yy',
                    'font_size': '20'}"></div>

<div ng-init="embyPoster={'item': 'EMBYPosterImage_URL',
                    'image_source': 'item-string',
                    'refresh': 5,
                    'intervaltype': 'seconds',
                    'background': 'transparent'}"></div>

<div ng-init="echoPoster={'item': 'Echo_Stereo_ImageUrl',
                    'image_source': 'item-string',
                    'refresh': 5,
                    'intervaltype': 'seconds',
                    'background': 'transparent'}"></div>

<div ng-init="bottomClock={'name': 'Bottom_Clock',
					 'mode': 'Digital\n\t\t    ',
                    'digital_format': 'h:mm a',
                    'font_size': '38'}"></div>
<div ng-init="temperature={ 'name': config.temperature_Name, 'item': config.temperature,
                    'type': 'dummy',
                    'useserverformat': true,
                    'font_size': '24' }"></div>
<div ng-init="echoTitle={ 'item': 'Echo_Stereo_Title',
                    'type': 'dummy',
                    'useserverformat': true,
                    'font_size': '16' }"></div>
<div ng-init="echoBand={ 'item': 'Echo_Stereo_Subtitle1',
                    'type': 'dummy',
                    'useserverformat': true,
                    'font_size': '16' }"></div>
  
<div ng-init="alarmStatus={ 'name': 'Alarm Status', 'item': 'Senser_Icon_Display',
                    'type': 'dummy',
                    'useserverformat': false,
                    'font_size': '24' }"></div>

<div class="container-fluid">
	<div class="row no-gutters">
		<div class="col-sm-8">

			<div ng-switch="itemState(config.view_item)">
			
				<div ng-switch-when="Knoxwebcameview">
					<widget-image ng-model="knoxRoom" style="margin:auto;"/>
				</div>
				
				<div ng-include="config.ngInclude_location"/>
				
				<div ng-switch-when="CameraKioskView">
					<div style="height: 800px">
						<div uib-carousel active="0" interval="5000" no-wrap="false">
							<div uib-slide index="0" >
								<widget-image ng-model="livRoom" style="margin:auto;"/>
							</div>
							<div uib-slide index="1">
								<widget-image ng-model="knoxRoom" style="margin:auto;"/>
							</div>
							<div uib-slide index="2" ng-init="model3 = { 'url':'http://192.168.50.5/zm/cgi-bin/nph-zms?mode=jpeg&monitor=4&scale=100&maxfps=15&buffer=1000&user=xxxxxx&pass=xxxxxxx', 'refresh': 1 }">
								<widget-image ng-model="model3" style="margin:auto;"/>
							</div>
							<div uib-slide index="3">
								<widget-image ng-model="neveRoom" style="margin:auto;"/>
							</div>
							<div uib-slide index="4">
     						<widget-image ng-model="outside" style="margin:auto;"/>
							</div>
 						</div>
					</div>
				</div>
				
				<div ng-switch-when="TabletFrontDoorOpen">
					<widget-image ng-model="livRoom" style="margin:auto;"/>
				</div>
 
				<div ng-switch-when="TabletDoorBellRung">
					<widget-image ng-model="livRoom" style="margin:auto;"/>
				</div>

			</div>
		</div>
      
		<div class="col-sm-4 d-flex align-items-center">
      
			<widget-clock ng-model="topClock"></widget-clock>
                    
			<div ng-if="itemValue('Display_EMBY_Poster')=='ON'">
				<widget-image ng-model="embyPoster"></widget-image>
			</div>
  
			<div ng-if="itemValue('Display_ECHO_Poster')=='ON'">
				<widget-image ng-model="echoPoster"></widget-image>
				<widget-dummy ng-model="echoTitle" style="color:#bec3bb;"></widget-dummy>
				<widget-dummy ng-model="echoBand" style="color:#bec3bb;"></widget-dummy>
			</div>

			<widget-clock ng-model="bottomClock"></widget-clock>

			<div ng-if="(itemValue('Display_EMBY_Poster')=='OFF')&&(itemValue('Display_ECHO_Poster')=='OFF')">
				<widget-dummy ng-model="temperature" style="color:#bec3bb;"></widget-dummy>
				<widget-dummy ng-model="alarmStatus" style="color:#bec3bb;"></widget-dummy>
			</div>
		</div>        
	</div>
 </div>
1 Like