1

In an ng-repeat list, I'm having a terrible time putting an ON/OFF button (using JQ UI wrapping radio buttons) for each item in the list.

When using radio buttons, it seems JQ UI buttonset needs both the "input" and "label" tags plus also the 'for' of the label must match the 'id' of the input.

I can use {{$index}} to make them unique, like this:

<label for='algoOn{{$index}}'>ON</label>
<input type='radio' [... blah blah ..] id='algoOn{{$index}}'>

The problem is calling $().buttonset() once the DOM is ready. I've tried various things (dom.ready, link function etc), but had to resort to calling it after a delay [ $('.buttonme').buttonset() ] to trigger all buttons on the page. Hacky.

However, I'd like to wrap the on/off button in a directive. Still have the same problems with needing unique IDs. (If you don't have unique IDs the buttons get bigger and bigger on each successful call in the directive's link function)

BUT... using {{$index}} in the template gives me a mysterious syntax error:

Syntax error, unrecognized expression: [for=on{{$index}}] <onoffbtn prop="win.runstate" class="ng-isolate-scope ng-scope">

(even though code doesn't have 'for=on{{$index}}' in it!)

The directive is the preferred approach but can't figure out how to get around this one.

Secondly, in the directive, all radio buttons are in sync after the first click, but when the page first loads the buttons in the directive are both blank. It doesn't set itself to the model right away. I thought to do that in the link function (eg. element -> find the input -> set the value) but angular has re-written all of the 'names' and 'ids'.

Plunker showing both issues is here: http://plnkr.co/edit/DTy8dGsRDVVDnWZBYlqQ

Thanks!

Danny
  • 2,482
  • 3
  • 34
  • 48

1 Answers1

1

Like you said this is doable from a directive. Using your html, I just added buttonset to the wrapping div:

<div id='A{{$index}}' buttonset>
  <label for='algoOn{{$index}}'>ON</label>
  <input class="buttonme" type='radio' name='onoff{{$index}}' ng-model='win.runstate' ng-name='onoff' value='running' id='algoOn{{$index}}'>
  <label for='algoOff{{$index}}'>OFF</label>
  <input class="buttonme" type='radio' name='onoff{{$index}}' ng-model='win.runstate' ng-name='onoff' value='stopped' id='algoOff{{$index}}'>
</div>

Here is how the buttonset directive looks

angular.module('button', [])
.directive('buttonset', function() {
    return function(scope, elm, attrs) {

      $(function(){
                 $(elm).buttonset();
            });      

    };
  });

Here is the plunker, no more hacks :)

Update: The errors you are getting have to do with the fact that the dwbuttonset directive is executing before the code is compiled by angular. Therefore, what you need to do is to wait until this has been done. You can use $timeout with a 0 value (see this question) in order to queue your method until everything has been loaded.

Example:

.directive('dwbuttonset', function($timeout){
  return function(scope, elm, attrs) {
      $timeout(function(){
          $(elm).buttonset();
      });        
}})
Community
  • 1
  • 1
Ulises
  • 13,229
  • 5
  • 34
  • 50
  • Thanks for responding! Indeed your directive works in the plunker. After integrating back into the main code, I still get the syntax error. The plunker was a little too simple I guess. I've made a new one that shows the problem: http://plnkr.co/edit/cAOG9zRkyXOwrwA1hCNu?p=preview It shows: Syntax error, unrecognized expression: [for=algoOn{{$index}}]
    – Danny Jan 18 '13 at 05:44
  • FYI, since jQuery is loaded before Angular, elm is already a jQuery wrapped element. So you can simply write `elm.buttonset()`. – Mark Rajcok Jan 19 '13 at 06:06