Angular - ng-disabled active/inactive

Problem

http://jsfiddle.net/zjqz6wjL/

I have 3 buttons, when you click on a button they all become disabled.

It would be nice if only the button I click becomes disabled and the other two remain active. When clicking on another button that one becomes disabled and in turn reactivating the previously disabled button back to active state.

        <button ng-click="disableClick()" ng-disabled="isDisabled" ng-model="isDisabled">Disable ng-click 1</button>
Problem courtesy of: Tom Rudge

Solution

You can do this :

angular.module('ngToggle', [])
    .controller('AppCtrl',['$scope', function($scope){
        $scope.btns = [
            {name:'1',isDisabled:false},
            {name:'2',isDisabled:false},
            {name:'3',isDisabled:false}
        ];
        $scope.disableClick = function(btn) {
            alert("Clicked!");
            angular.forEach($scope.btns,function(_btn){
                _btn.isDisabled = false;
            });
            btn.isDisabled = true;
            return false;
        }
}]);

With this template :

<body ng-app="ngToggle">
    <div ng-controller="AppCtrl">
        <button ng-repeat="btn in btns" ng-click="disableClick(btn)" ng-disabled="btn.isDisabled">Disable ng-click {{btn.name}}</button>
    </div>
</body>

See here : https://jsfiddle.net/dy7g0snx/

  • You don't need the ng-model directive here (it was unsed though).
  • Use your btns as objects
  • Get it as array
  • Use ng-repeat directive to loop on it
  • Pass the btn object in disableClick method
  • Disable all buttons in the method
  • Then enable the passed button

EDIT

Inspired by the comment then the answer of Joaozito Polo, here an alternative if you don' want to use objects. It is not recommended in most case but with a use case with only 2 or 3 buttons, non-paramtric, it is acceptable.

In a such situation, you didn't need the $scope.disableClick() thus, no more need the controller too.

Just declare your angular module js-side :

angular.module('ngToggle', []);

And use ng-click then ng-disable directives in content corelations :

<body ng-app="ngToggle">
    <button ng-click="disabled = 1" ng-disabled="disabled == 1">Disable ng-click 1</button>
    <button ng-click="disabled = 2" ng-disabled="disabled == 2">Disable ng-click 2</button>
    <button ng-click="disabled = 3" ng-disabled="disabled == 3">Disable ng-click 3</button>
</body>

Note that I removed the ng-controller directive too, because it will not defined js side now.

See the demo here

Solution courtesy of: Rémi Becheras

Discussion

Here is what I have managed to do without use of controllers :

<body ng-app="ngToggle">
<div ng-controller="AppCtrl" ng-init = "disabled=0">
    <button ng-click = "disabled = disabled == 1 ? 0 : 1"  ng-disabled="disabled == 1" ng-model="isDisabled">Disable ng-click 1</button>
   <button ng-click="disabled = disabled=== 2 ? 0 : 2" ng-disabled="disabled == 2" ng-model="isDisabled">Disable ng-click 2</button>
   <button ng-click="disabled = disabled=== 3 ? 0 : 3" ng-disabled="disabled == 3" ng-model="isDisabled">Disable ng-click 3</button>
</div>

here is the fiddle : http://jsfiddle.net/zjqz6wjL/8/

Discussion courtesy of: Shankar Regmi

You can store the last clicked button information, and check on ngDisabled:

<button ng-click="click(1)" ng-disabled="lastClicked == 1">Disable ng-click 1</button>

and your action:

$scope.click = function(btn) {
    alert("Clicked!");
    $scope.lastClicked = btn;
    return false;
}

You can see on jsfiddle

Discussion courtesy of: Joaozito Polo

You can choose to extract to independent directives. There are two directives: buttonGroup and myButton. In buttonGroup, the property disabledBtnName stores the name of the only disabled button. In ng-repeat, only the button with name disabledBtnName will be disabled. It is easy to be reused, say, in many different pages.

angular.module('ngToggle', [])
    .directive('buttonGroup', [function () {
    return {
        restrict: 'A',
        transclude: true,
        scope: {},
        template:
            '<div>' +
            '<button ng-repeat="btn in buttons" ng-disabled="btn.name == disabledBtnName" ng-click="disableMe(btn)" ng-bind="btn.text"></button>' +
            '<div ng-transclude></div>' +
            '</div>',
        controller: ['$scope', function ($scope) {
            $scope.buttons = [];
            this.addButton = function (btn) {
                $scope.buttons.push(btn);
            };
            $scope.disableMe = function (btn) {
                $scope.disabledBtnName = btn.name;
            };
        }]
    };
}])
    .directive('myButton', [function () {
    return {
        restrict: 'A',
        scope: {
            name: '@',
            text: '@'
        },
        require: '^buttonGroup',
        link: function (scope, iElement, attrs, btnGroupCtrl) {
            btnGroupCtrl.addButton(scope);
        }
    };
}]);

Simply use it like:

<body ng-app="ngToggle">
    <div button-group>
        <div my-button name="one" text="Button One"></div>
        <div my-button name="twp" text="Button Two"></div>
        <div my-button name="three" text="Button Three"></div>
    </div>
</body>

Check the online working demo: http://jsfiddle.net/zjqz6wjL/4/

Discussion courtesy of: Joy

This recipe can be found in it's original form on Stack Over Flow.