2

I'm getting started with writing directives and I'm pretty sure I grasp the whole concept of defining an 'isolate' scope for a directive.

My directive numberRoulette is supposed to animate each digit (or a supplied number of digits through attribute fields="some-number-here") in a supplied number with random numbers. Every elapsed second, one digit stops animating and is set to its intended number. It 's a bit like a slot machine..

<div ng-app="myApp">
  <div ng-controller="MasterCtrl">
    <span number-roulette fields="10" ng-model="number">
      {{number}}
    </span>
  </div>
</div>

The problem I'm running into is that when I make a two-way binding between the directive scope and a scope used by a controller MasterCtrl, my values stop displaying.

app.directive('numberRoulette', function($timeout) {
  return {
    restrict: 'A',
    scope: {showNumber: '=ngModel'},
    ...
  };
});

function MasterCtrl($scope) {
  $scope.number = 1000;
}

JSFiddle: http://jsfiddle.net/nguyening/aX6Zm/3/

actaeon
  • 695
  • 1
  • 8
  • 17

1 Answers1

5

Use {{showNumber}} or move {{number}} outside the span.

Inside the span, you have access to the directive scope properties only (e.g., showNumber), because an isolate scope was created for the directive.

Outside the span, you have access to the controller scope properties, e.g., number.

Update: ng-model isn't required here. Any attribute will do, e.g.:

<span number-roulette fields="10" model="number">

Then in the directive:

scope: {showNumber: '=model'},
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • +1 as this is the right answer. But, for completeness, you could also use transclusion. – Josh David Miller Jan 08 '13 at 23:05
  • 1
    As per @Josh's suggestion, here is a jsfiddle that uses transclusion instead: http://jsfiddle.net/mrajcok/aX6Zm/6/. With this solution, we use `{{number}}` inside the span. – Mark Rajcok Jan 09 '13 at 03:39
  • followup: say I remove the attribute `ngModel` from the span. If I'm `transclude`ing, how do I use the function passed into `compile` to access the sibling scope? – actaeon Jan 09 '13 at 04:07
  • @actaeon, I'm not sure I follow you, but I think you're considering how to access the `number` property from the transcluded scope (since it prototypically inherits from the parent/controller scope). I don't think this is how the transclude linking function is normally used. From what little I've read about that function, it is normally only used to preprocess the content (i.e., "{{number}}") prior to being transcluded. See [this SO question](http://stackoverflow.com/questions/13183005/what-exactly-do-you-do-with-the-transclude-function-and-the-clone-linking-functi). – Mark Rajcok Jan 09 '13 at 04:54
  • @MarkRajcok: how do I then go about modifying `{{number}}` within the `compile` function if I choose not to add it as an attribute of my directive, i.e. `scope: {localProp: '=attr'}`? – actaeon Jan 09 '13 at 05:08
  • @actaeon, I would do this in the linking function (you don't need a compile function). If you don't want an attribute, you can remove the `scope: ...` line from your directive and the directive will use the same scope as the parent. Or you can use `scope: true` and the directive will get its own child scope that prototypically inherits. Here's a [fiddle](http://jsfiddle.net/mrajcok/TwaDG/) of the former. For more on directive scopes, see [this post/article](http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs) – Mark Rajcok Jan 09 '13 at 05:18
  • @MarkRajcok: Thanks for the help and resources! I guess I was stuck on the idea that I needed to use an isolate scope for my directive for it to be reusable in multiple instances, and I didn't want to pollute the parent scope with my functions and such. It makes more sense to inherit from the parent if I want to work with it this way. – actaeon Jan 09 '13 at 05:23