itemValue to local variable

This custom widget stuff is really great and my russound widget is starting really to evolve (have about 6 screens built into it now). The biggest issue is that I need to update some local state from channel and more importantly - update the local state when the item value changes.

Overly simple example:

<div ng-init="mystate = { pageid: 'main' }"/>
<div ng-if="mystate.pageid=='main'">...</div>
<div ng-if="mystate.pageid=='dialog'">...</div>

What I need is for “mystate.pageid” to change based on itemValue(mychannel).
Note: I realize in my overly simple example that I could simply eliminate “mystate.pageid” and change the ng-if to use the itemvalue directly. My actual situation is much more complex - the example is just for demonstration of what I need.
Note2: I also realize I’m abusing ng-init - but since I can’t define a controller, I don’t have much else in the way of defining my own psuedo values. Correct me if I’m wrong on that…

I can’t figure out how to change “mystate” based on changes to itemValue(mychannel).

I tried

<div ng-init="mystate = { pageid: itemValue(mychannel) }"/>

Works for the initial value but obviously won’t be updated with changes

<input type='hidden' ng-model="mystate.pageid" value="{{ itemValue(mychannel) }}"/> 

Hoping that the ‘value’ would be updated on changes and ng-model would feed it back to mystate.pageid. No go.

<input type='hidden' ng-model="itemValue(mychannel)" ng-onchange="mystate.pageid=itemValue(mychannel)"/> 

Angular complains that itemValue(mychannel) isn’t eligible to be a model (because it’s a function).

Any suggestions (to update a variable like that from channel values) or different approaches (to eliminate the ng-init, define my own controller, modify a controller or whatever else where I can defined my own variables to use)?

Thanks,
Tim

BTW - thanks for the work on this. HABPanel is really great!

1 Like

I feel like I’m opening a can of worms… :wink:

This is uncharted territory, for advanced use cases, and don’t expect much support :slight_smile:

You can define a controller by using the ocLazyLoad directive in your template and loading a file sitting on your openHAB server - other servers won’t work at least in modern browsers thanks to the Content Security Policy in place; still it’s important to know there is always a risk of malicious code being injected especially if your openHAB is exposed to the internet! (There are no plans of allowing controllers to be injected dynamically without access to the server’s filesystem for now.).

/conf/html/mycontroller.js:

angular
    .module('app.widgets')
    .controller('MyWidgetCtrl', testCtrl);

testCtrl.$inject = ['$scope', 'OHService'];
function testCtrl($scope, OHService) {
  var vm = this;
  vm.myvalue = "testing123";

  OHService.onUpdate($scope, 'Yamaha_Input', function () {
    var item = OHService.getItem('Yamaha_Input');
    if (item) {
      vm.myitem = item.state;
    }
  });

}

Then you can load/bind it in your template with:

<div oc-lazy-load="['/static/mycontroller.js']">
  <div ng-controller="MyWidgetCtrl as myctrl">
		<input class="form-control" type='text' ng-model="myctrl.myitem" />
  </div>
</div>

(Note the “as myctrl” syntax and the var vm = this in the controller, this way you still have access to the methods in the parent scope - the template widget itself - if you need them).

You could also build a complete directive with its own template etc.

2 Likes