2

I'm looking for an AngularJS-friendly way to show an input box and select the text within the input. I've tried using the controller to add the logic, this is what I have so far:

HTML ComparisonCenterProfiles.html

<div id="saved-profiles" class="select-list" ng-cloak>
    <ul>
        <li ng-repeat="profile in profiles" ng-class="{'ellipsis': true, 'active': isActive(profile.CompSetId)}">
            <span class="save-disk" ng-click="saveActiveProfile()" ng-show="isActive(profile.CompSetId) && profile.IsDirty" style="cursor: pointer;"></span>

            <a href="javascript:;" ng-show="!forceRenameProfile || !isActive(profile.CompSetId)" ng-click="setActiveProfile(profile)">{{profile.CompSetName}}</a>

            <input type="text" ng-model="profile.CompSetName" ng-show="forceRenameProfile && isActive(profile.CompSetId)" ng-blur="saveActiveProfile()" />

        </li>
    </ul>
</div>

Javascript

angular
.module('app')
.directive('compProfiles', ['pageMethod', function (pageMethod) {
    return {
        restrict: 'E',
        require: '^compEditor',
        controller: ['$scope', function ($scope) {
            $scope.saveActiveProfile = function () {
                if ($scope.activeProfile.CompSetName.length < 3) {
                    showAlert('Error',
                                '<strong>' + $scope.activeProfile.CompSetName + '</strong> is not a valid profile name. Your profile name must have at least 3 characters.',
                                [
                                    {
                                        text: 'OK',
                                        click: function () {
                                            $scope.forceRenameProfile = true;
                                            hideAlert($(this));
                                        }
                                    }
                                ]);
                }
                else {
                    continueSavingProfile();
                    $scope.forceRenameProfile = false;
                }
            }
        }],
        templateUrl: 'Templates/ComparisonCenterProfiles.html'
    };
}]);

So at this point, I'm able to show the input box but have been unable to actually select the text within the input box in order to emphasize that the user needs to change the contents within the box.

Sidenote: I'm newer to AngularJS and, coming from a jQuery background, I of course tried using focus() and select() on the element to no avail.

Any ideas would be appreciated!

isherwood
  • 58,414
  • 16
  • 114
  • 157
John Paez
  • 65
  • 3
  • 8
  • When validation fails, I show the textbox so that the user can edit the name of the profile... I need the application to also select the text inside the textbox when it becomes visible. – John Paez Jun 02 '16 at 19:26
  • This answer talks about text selection. http://stackoverflow.com/questions/14995884/select-text-on-input-focus – isherwood Jun 02 '16 at 19:58
  • Changed the topic name to add make it a bit more specific... I don't need the text to be selected on a click event; I need the text to be selected from the directive's controller .js file. Right now I can make the element visible but I can't select the text from the controller. – John Paez Jun 03 '16 at 05:40
  • To select text, you must have a reference to your element in your directive. To do that you must implement a link function (https://docs.angularjs.org/guide/directive). This function will provide the html element (in your case the head node of your directive template, but you can find the input inside). After to have save the reference of the element in the directive you can call setSelectionRange on the element – Silvinus Jun 03 '16 at 06:27
  • Please don't prepend tags in topic titles. That's what tags are for. Lots of discussion in Meta if you're curious. http://meta.stackoverflow.com/questions/253028/why-is-removing-tags-from-the-title-suggested-so-often – isherwood Jun 03 '16 at 13:40

2 Answers2

1

You can get the input element from link directive. Add this function into directive:

link: function(scope, element) {
   var inputElement = element.find('input');
   scope.selectText = function() {
       inputElement.setSelectionRange(0, inputElement.value.length)
   }
}

And in your controller you can call selectText function :

scope.selectText();
Silvinus
  • 1,445
  • 8
  • 16
1

Thanks for your help Silvinus... I used a combination of your answer (using the link instead of the controller and using .setSelectionRange()) along with How to set focus on input field? post to come up with this final solution:

HTML

<input type="text" ng-show="forceRenameProfile && isActive(profile.CompSetId)" focus-me="forceRenameProfile && isActive(profile.CompSetId)" ng-model="profile.CompSetName" ng-blur="saveActiveProfile()" />

Javascript

.directive('focusMe', function ($timeout, $parse) {
        return {
            link: function (scope, element, attrs) {
                var model = $parse(attrs.focusMe);
                scope.$watch(model, function (value) {
                    if (value) {
                        $timeout(function () {
                            element[0].focus();
                            element[0].setSelectionRange(0, element[0].value.length);
                        });
                    }
                });
            }
        };
    });

This solution allowed me to use the same conditional for showing as for focusing and selecting.

Community
  • 1
  • 1
John Paez
  • 65
  • 3
  • 8