Search code examples
angularjsangularjs-directiveangularjs-scopeangularjs-ng-click

How do you fire a button click that does different things based on which Controller is on the view?


QUESTION

How do you fire a button click that does different things based on which Controller is on the view?

SITUATION

Below I have two directives/controllers that share the same template view. All the data is rendering correctly - the ng-click="{{::vm.action}}" however doesn't do anything on click. If I change the syntax to ng-click="{{::vm.action()}}" ... the code breaks for view.

CODE

main.html

<confirm-modal></confirm-modal>

<error-modal></error-modal>

modal.html:

<article>
    <h1>{{::title}}</h1>
    <p>{{::body}}</p>
    <button ng-click="{{::action}}">{{::button}}</button>
</article>

confirm-modal.directive.js (and controller)

angular
  .module('common.modal')
  .controller('ConfirmModalController', ConfirmModalController)
  .directive('confirmModal', confirmModal);

/* @ngInject */
function confirmModal() {

  var directive = {
    templateUrl: 'app/widgets/modals/modal.html',
    restrict: 'E',
    controller: ConfirmModalController,
    controllerAs: 'vm',
    bindToController: true
  };

  return directive;
}

function ConfirmModalController(modalService) {

  var vm = this;

  vm.title = 'Confirm Your Subscription';

  vm.body = '$8.99 per month will be billed to your account.';

  vm.button = 'Subscribe';

  vm.action = function () {
    console.log('confirm subscription');
    modalService.confirmSubscription();
  };

}

error-modal.directive.js (and controller)

angular
  .module('common.modal')
  .controller('ErrorModalController', ErrorModalController)
  .directive('errorModal', errorModal);

/* @ngInject */
function errorModal() {
  var directive = {
    templateUrl: 'app/widgets/modals/modal.html',
    restrict: 'E',
    controller: ErrorModalController,
    controllerAs: 'vm',
    bindToController: true
  };

  return directive;
}

function ErrorModalController(modalService) {

  var vm = this;

  vm.title = 'There was an error with your request';

  vm.body = 'Please contact administrator regarding this error';

  vm.button = 'Dismiss';

  vm.action = function () {
    console.log('error on subscription');
    modalService.closeAllModals();
  };
}

Solution

  • {{::vm.action}} is a reference to the function vm.action while {{::vm.action()}} executes that function when the template is rendered. Angular is binding the return value of that function (undefined in this case) to your ng-click. Just get rid of the Angular expression delimiters in the click handler:

    <article>
        <h1>{{::vm.title}}</h1>
        <p>{{::vm.body}}</p>
        <button ng-click="vm.action()">{{::vm.button}}</button>
    </article>
    

    Edit: Sorry. Forgot the ()