AngularJS: How to not lose focus on element if oth

2019-07-23 04:26发布

问题:

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.

回答1:

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.