Naomi
Naomi

Reputation: 718

Conditional focus

I have this directive:

(function () {
    'use strict';

    var app = angular.module('myAppName');

    app.directive('smFocus', [ '$timeout', function ($timeout) {
        return {
            restrict: 'A',            
            link: function (scope, element) {

                scope.$on('sm:focus', function () {
                    $timeout(function() {
                        element[0].focus();
                    }, 10);
                });
            }
        };
    }]);
})();

I also have these two controls:

<input type="text"
                               name="nickname"
                               id="nickname"
                               ng-model="currentDynamicRule.nickname"
                               class="form-control"
                               ng-disabled="!isNew"
                               placeholder="Nickname"
                               required
                               ng-maxlength="10"
                               sm-focus />

and another one

 <input type="text" name="descrip" id="descrip" ng-model="currentDynamicRule.descrip" class="form-control"
                           placeholder="Description" required ng-maxlength="30"
                           sm-focus />

So, two controls where the first one is only enabled when it's a new row (disabled in Edit mode). I want to have the first control focused when it's a new record and the second control focused when it's in edit mode.

I am using ASP.NET MVC. Right now in both edit and new modes I have the second control focused. I am not sure how to make this focus conditional.

Upvotes: 0

Views: 2011

Answers (2)

Naomi
Naomi

Reputation: 718

Here is my current implementation that seems to be working! Need to test more:

app.directive('smFocus', [ '$timeout', function ($timeout) {
        return {
            restrict: 'A',
            scope: {
                noFocus: "=?"
            },
            link: function (scope, element) {
                var noFocus = angular.isDefined(scope.noFocus) ? scope.noFocus : false;
               // console.log('noFocus=' + noFocus)
                if (!noFocus) {
                    scope.$on('sm:focus', function () {
                        $timeout(function () {
                            element[0].focus();
                        }, 10);
                    });
                }
            }
        };

And my form controls are:

 <input type="text"
                           name="nickname"
                           id="nickname"
                           ng-model="currentDynamicRule.nickname"
                           class="form-control"
                           ng-disabled="!isNew"
                           placeholder="Nickname"
                           required
                           ng-maxlength="10"
                           no-focus="!isNew"
                           sm-focus />

And similar for description:

 <input type="text" name="descrip" id="descrip" ng-model="currentDynamicRule.descrip" class="form-control"
                           placeholder="Description" required ng-maxlength="30"
                           no-focus="isNew"
                           sm-focus />

The form works as I want it. I am going to test few more forms to make sure this change didn't break anything.

Upvotes: 0

ryeballar
ryeballar

Reputation: 30088

hmm I had written a directive before wherein it accepts an event and an element id to focus when that event has been triggered.

It's something like this(Plunker DEMO):

JAVASCRIPT

  .directive('eventFocus', function($timeout) {
    return function(scope, elem, attr) {
      elem.on(attr.eventFocus, function() {
        // timeout makes sure that is invoked after any other event has been triggered.
        // e.g. click events that need to run before the focus or
        // inputs elements that are in a disabled state but are enabled when those events
        // are triggered.
        $timeout(function() {
          var element = document.getElementById(attr.eventFocusId);
          if(element)
            element.focus();
        });
      });

      scope.$on('$destroy', function() {
        element.off(attr.eventFocus);
      });
    };
  })

HTML (Possible implementation)

<input type="text" id="pet-desc" ng-model="pet.desc">
<button type="button" event-focus="click" event-focus-id="pet-desc">Edit</button

When Edit Button is clicked, input with id="pet-desc" is focused.

UPDATE: To identify between which sm-focus element is the target for the sm:focus event, you can add an argument(the id of the element to focus to) within your $rootScope.$broadcast(). See this PLUNKER.

e.g.

Controller

$rotoScope.$broadcast('sm:focus', 'pet-id');

Directive

  directive('smFocus', function($timeout) {
    return function(scope, elem, attr) {
      scope.$on('sm:focus', function(event, id) {
        $timeout(function() {
          if(attr.id == id)
            elem[0].focus();
        });
      });
    };
  })

Upvotes: 1

Related Questions