0

I know this question has been asked about 100 times (trust me, I've read them all), but I'm having trouble getting focus to go to an input box when the directive does NOT use isolate scope. The scope.$watch doesn't fire when the backing data changes.

Why not just use the one with isolate scope, you ask? Well, my understanding is that you should ONLY use isolate scope if your directive has a template.

The only differences in the directives is:

// works
app.directive('doesFocus', function ($timeout) {
    return {
        scope: { trigger: '@doesFocus' },
        link: function (scope, element) {
            scope.$watch('trigger', function (value) {
              // sets focus
            }
            ...

// does not work, and in fact when I inspect attrs.doesNotFocus it is undefined
app.directive('doesNotFocus', function ($timeout) {
    return {
        scope: false,
        link: function (scope, element, attrs) {
            scope.$watch(attrs.doesNotFocus, function (value) {
              // sets focus
            }
            ...

I'm on week 3 of using Angular, so I must be missing some silly semantic issue.

Here is a fiddle illustrating my issue. http://jsfiddle.net/tpeiffer/eAFmJ/


EDIT

My actual problem was that my real code was like this (hazard of mocking the problem, you sometimes mask the real problem):

<input should-focus="{{isDrawerOpen()}" ... ></input>

but because I was using a function, not a property, I was missing the required ticks

<input should-focus="{{'isDrawerOpen()'}}" ... ></input>

Making this change fixed the problem and my directive can still be like this:

scope.$watch(attrs.shouldFocus, focusCallback(newValue));

END EDIT


Thanks for helping me in my quest for angular excellence!

Thad

Thad Peiffer
  • 638
  • 1
  • 7
  • 22
  • As @Mitch suggested, changing my fiddle so that the non-isolate scoped directive watched the scope variable, not the attribute worked. All of the examples I found had the $watch on the attrib.directiveName. Hope this helps others! – Thad Peiffer Aug 08 '13 at 18:55

2 Answers2

1

Remove {{}} from your HTML. So instead of:

<input class="filter-item" placeholder="Enter filter" 
 does-not-focus="{{bottomDrawerOpen}}" type="text">

use

<input class="filter-item" placeholder="Enter filter" 
 does-not-focus="bottomDrawerOpen" type="text">

Then it works with watching attrs.doesNotFocus:

scope.$watch(attrs.doesNotFocus, function (value) {...} );

Fiddle

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Ah, yes, I see that works, too, and in fact is the way it is in other examples I've seen. Hmm, have I developed bracket blindness? :) – Thad Peiffer Aug 09 '13 at 17:30
0

Your bottom drawer was watching a function isDrawerOpen(), not a property.
Change

   scope.$watch('isDrawerOpen()',...);

to

   scope.$watch('toggleBottomDrawer',...);
mitch
  • 1,821
  • 14
  • 14
  • Shoot. Was playing with the fiddle and changed it. The value in the second SHOULD have been attrs.doesNotFocus (like in the code in my post). Using attrs.directiveName was how it was in all of the other posts I saw: http://stackoverflow.com/questions/14833326/how-to-set-focus-in-angularjs http://stackoverflow.com/questions/14076783/angularjs-focusing-a-input-element-when-a-checkbox-is-clicked But hey, since doing it like you suggest works, then I like it!! Thanks!! – Thad Peiffer Aug 08 '13 at 18:50
  • Yup! Updated my post to reflect the fix. Thanks!! – Thad Peiffer Aug 08 '13 at 18:55