1

I'm am aware that dom manipulation isn't suppose to be in the controllor so I was curious on what the proper "Angular" way to handle these jquery events.

Here is one of my controllers function

    $scope.record = function (){
        $scope.slideChanges.push($scope.display);
        $scope.syncTimer.push(0);
        $scope.flashObject.doRecord();
        $("#Pause").removeClass().addClass("btn btn-warning");
        $("#Resume").removeClass().addClass("btn btn-default disabled");
        $("#Stop").removeClass().addClass("btn btn-danger");
        $("#Restart").removeClass().addClass("btn btn-primary");
        $("#Record").removeClass().addClass("btn btn-danger disabled");

    };

So I could I remove the dom manipulation outside of this function but still achieve the same effect.

Austin Davis
  • 3,516
  • 10
  • 27
  • 47
  • 1
    Think declarative, store the current state on the $scope. For your example you could have a flag `$scope.player.isRecording = true/false;`, then your #Pause element for example could have a: `ng-class="{ 'btn-warning': player.isRecording }"` and your resume button: `ng-class="{ 'btn-default': player.isRecording }" ng-disabled="player.isRecording"`. It depends too much on the actual context to have a one size fits all solution. For the invocation of functions, using the controller isn't bad. (Remember that the controller is a viewmodel, it's a model specially developed to add power to a view.) – Aidiakapi Dec 24 '13 at 21:07
  • thx for the response. So for instance is if my pause element needed to listen to for instance 4 different state I would need something like 4 different flags and my #pause element would have something like ng-class="{ 'btn-warning': player.isRecording , 'btn-success' : player.isStoped ...} – Austin Davis Dec 24 '13 at 21:12
  • That's why I said it highly depends on the situation, in some cases you just want to control the player state (whether it's recording, playing, etc.), other times you want to assign the state of the interface (whether pause button should be enabled). However most of the time the cleanest most maintainable code is from the first approach. Instead of different flags you can also just have a single field status: `$scope.playerStatus = 'paused';`, and `ng-class="{ 'btn-warning': playerStatus=='recording' || playerStatus=='playing', 'btn-success': playerStatus=='stopped' }"`. – Aidiakapi Dec 24 '13 at 21:17
  • If the control is complex, you can turn it into a directive with a template that abstracts all that away. For a recorder/player that most certainly seems like something I'd always choose rather than putting it all in one view. Separation makes it easier to test, and to keep things easier to comprehend. – Aidiakapi Dec 24 '13 at 21:18
  • Ya I figured. I would need a template. I just haven't it just the angular js documentation hasn't been super helpulf to me/for learning how to build custom directives/templates – Austin Davis Dec 24 '13 at 21:24
  • I've had the exact same problem when first starting, I didn't find very many good resources on AJS directive. I've learned a lot from https://egghead.io. I'm also working on writing an answer with an example right now :) – Aidiakapi Dec 24 '13 at 21:26
  • Have a look at http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background –  Jan 03 '14 at 02:47

1 Answers1

1

You can create an entire mediaplayer directive, or you can use it inline using the method I described in the comments. However I feel like abstracting it makes it feel cleaner.

This plnkr contains the working example of how you can create some sort of media player directive that is bound by a state.

The resulting code in the view is minimal:

<div pf-music-player="somePlayer" file="{{fileToPlay}}"></div>

The template of the directive looks like:

<span class="btn-group">
  <button class="btn" ng-disabled="state == states.Waiting || state == states.Loading"
    ng-class="{
        'btn-success': state == states.Stopped || state == states.Paused,
        'btn-danger': state == states.Playing
    }" ng-click="play()">Play</button>
  <button class="btn" ng-disabled="state == states.Waiting || state == states.Loading"
    ng-class="{
        'btn-success': state == states.Playing || state == states.Recording,
        'btn-danger': state == states.Paused
    }" ng-click="pause()">Pause</button>
  <button class="btn" ng-disabled="state == states.Waiting || state == states.Loading"
    ng-class="{
      'btn-success': state == states.Stopped || state == states.Paused,
      'btn-danger': state == states.Recording
    }" ng-click="record()">Record</button>
  <button class="btn" ng-disabled="state == states.Waiting || state == states.Loading"
    ng-class="{
      'btn-success': state == states.Playing || state == states.Recording || state == states.Paused,
      'btn-danger': state == states.Stopped
    }" ng-click="stop()">Stop</button>
</span>
<p ng-show="state != states.Waiting &amp;&amp; state != states.Loading">Playing {{songName}}</p>

The functions play(), pause(), record(), stop() and fields state, states and songName are supplied by the directive's link function.

For the implementation of the directive take a look at the plnkr.

Aidiakapi
  • 6,034
  • 4
  • 33
  • 62
  • you might want to put the template code in your answer just for other user's quick reference – Austin Davis Dec 24 '13 at 22:15
  • I think it's too large to put in a post, especially because it spans multiple files. But I'll add the code for the template alone. – Aidiakapi Dec 24 '13 at 22:29