VolcovMeter VolcovMeter - 4 months ago 35
AngularJS Question

AngularJS: How to not lose focus on element if other elements are clicked (using ng-focus/ng-blur)?

I've got some elements inside an

ng-repeat
loop that have these attributes:

<div ng-repeat="h in myObjectArray">
<div>
<input ng-class="{ clicked: clickedFlag1 }" ng-focus="clickedFlag1 = true" ng-blur="clickedFlag1 = false" type="button" id="1" value="1" ng-click="btnSelected(1)" />
</div>
<div>
<input ng-class="{ clicked: clickedFlag2 }" ng-focus="clickedFlag2 = true" ng-blur="clickedFlag2 = false" type="button" id="2" value="2" ng-click="btnSelected(2)" />
</div>
</div>


What happens is when one of the elements is clicked, it add class
clicked
to the clicked element, and removes the
clicked
class from all other button inputs.

The problem is, if I click on any other element on the rest of the page, the element I previously clicked no longer has focus and gets it's
clicked
class removed.

Is there anyway to still use
ng-focus
and
ng-blur
like I am using above but have the element that's clicked to have
clicked
class even when other elements on the page are clicked?

To explain: Previously before going about this solution, I was locating elements via
querySelector
, adding and removing classes that way. Someone pointed out that using DOM through AngularJS this way wasn't efficient, so I went with this way.

The problem initially was to select one button and ONLY that button to hold a
clicked
class.

Now the problem is for that element to hold that clicked class if anything else is selected on the page.

Answer

Now when I know what you're trying to do, this is my suggestion

<div ng-repeat="h in myObjectArray">
    <div>
        <input ng-class="{ clicked: clickedFlag1 == $index }" ng-click="btnSelected(1, $index)" type="button" ng-attr-id="btn1_{{ $index }}" value="1" />
    </div>
    <div>
        <input ng-class="{ clicked: clickedFlag2 == $index }" ng-click="btnSelected(2, $index)" type="button" ng-attr-id="btn2_{{ $index }}" value="2" />
    </div>
</div>

Now, on your controller, change the btnSelected function and allow it to accept the second parameter:

$scope.btnSelected = function(btnNumber, btnIndex) {
    if( btnNumber == 1 ) {
        $scope.clickedFlag1  = btnIndex;
    } else {
        $scope.clickedFlag2  = btnIndex;
    }
    // .... rest of your code
}

Note that btnNumber is a made up name, replace it with the current parameter name you're using in your function.

When you're inside ngRepeat you have $index that reference to the current index in the loop, so when you click on the button, you set clickFlag1 = $index when you click on the first button (from within the controller) on every button groups OR clickFlag2 = $index for the second button.

This will allow the ngClass to set the click class on the button based on the current index, instead of trusting the focus/blur.

FYI - Having multiple elements with the same id is a bad practice (you're inside ngRepeat), you can change the current id to ng-attr-id="btn1_{{ $index }}" for the first button on each group, and ng-attr-id="btn2_{{ $index }}" for the second button. Don't forget to remove the current id attributes.

Comments