Phix
Phix

Reputation: 9890

Passing ng-click through to template

I've found a few answers relating to this question, but I'm getting (at best) an "unexpected token" error.

I'm attempting to build a library of directives around the bootstrap framework to make markup lighter and my job easier when using bootstrap with angular. First up is a glyph-button:

angular.module('angular-bootstrap', [])
.directive('glyphBtn', function(){

// Allowed button sizes
var _allowedSizes = ['xs', 'sm', 'lg'],
    _defaultClass = "btn-primary";

return {
  restrict :'EA',
  transclude : true,
  replace : true,
  scope : {
    clickHandler : '&ngClick',
    glyph : '@',          // The glyph name, defined at http://getbootstrap.com/css/#buttons
    size : '@',           // Size of the button, lg, sm, xs
    bsClass : '@',           // "Class" of button, default, primary, success, info, warning, danger, link
    isActiveFn : '&',        // The function which dictates the buttons "active state"
    spaces : '@'
  },
  compile : function(tElement, tAttrs){
    // Normalize to btn-primary
    if(!tAttrs.bsClass)
      tAttrs.bsClass = _defaultClass;

    // Default size is empty string
    if(!tAttrs.size)
      tAttrs.size = "";

    // Link function:
    return function(scope, element, attrs){
      scope.getSpaces = function(){
        if(parseInt(scope.spaces) > 0)
          return " "; // only one space allowed in HTML
      }
      scope.getBSClass = function(){
        return attrs.bsClass;
      }
      scope.getSize = function(){
        if(_allowedSizes.indexOf(attrs.size) == -1)
          return '';
        return "btn-" + attrs.size;
      }
    }
  },
  template : '<button type="button" class="btn {{getBSClass()}} {{getSize()}}" ng-transclude><span class="glyphicon glyphicon-{{glyph}}"></span>{{getSpaces()}}</button>'
}
})

/* Usage:
<button glyph-btn 
  glyph="align-center" 
  isActiveFn="doToggle()" 
  size="sm"
  type="primary">Some Text</button>
*/

I'd like to have the ng-click method attached to the directive node, i.e.

<button glyph-btn glyph="chevron-right" size="lg" spaces="1" ng-click="test()">Test Button</button>

But I can't seem to get the ng-click method to "pass through" to the ng-click of the button in the template. The best I can get is it being called like 4 times on load, and at worst nothing happens.

Answers I've looked at:

My controller:

.controller('HomeCtrl', function($scope){
  $scope.test = function(){
    console.log("test")
  }
})

It could be just late in the night, but for the life of me I can't figure out why adding an ng-click="clickHandler()" would throw the following error:

Error: Syntax Error: Token 'clickHandler' is an unexpected token at column 8 of the expression [test() clickHandler()] starting at [clickHandler()].

Everything else works fine, but passing ngClick (and I'm sure later when I try ngClass) it doesn't want to play nice.

Angular 1.0.8

Edit

When the error is thrown, the incomplete (unparsed) markup shown in the console is:

<button type="button" ng-click="test() _clickHandle()" class="btn {{getBSClass()}} {{getSize()}}" ng-transclude="" glyph-btn="" glyph="chevron-right"><span class="glyphicon glyphicon-{{glyph}}"></span>{{getSpaces()}}</button>

Which you can see it's copying both the method I pass in through the attributes of the directive (test()), AND the scope method from the directive's return into the ng-click attribute:

return {
restrict :'EA',
transclude : true,
replace : true,
scope : {
  _clickHandle : '&ngClick',
  glyph : '@',          // The glyph name, defined at http://getbootstrap.com/css/#buttons
  size : '@',           // Size of the button, lg, sm, xs
  bsClass : '@',           // "Class" of button, default, primary, success, info, warning, danger, link
  isActiveFn : '&',        // The function which dictates the buttons "active state"
  spaces : '@'
}

Adding the surrounding <div> works, but that's silly and can break things (CSS, etc). What am I missing?

Upvotes: 0

Views: 652

Answers (1)

Ajay Singh Beniwal
Ajay Singh Beniwal

Reputation: 19037

You have to wrap button inside a div and your problem will go away

<div><button glyph-btn glyph="chevron-right" size="lg" spaces="1" ng-click="test()">Test Button</button></div>

Upvotes: 1

Related Questions