14

I've got a simple contactList component, which has 2 bindings: contacts and onRemove.

  • contacts is just an array of contacts to display
  • onRemove is a callback function
app
  .component('contactList', {
    template: 
      `<div ng-repeat="c in $ctrl.contacts">
         {{c.name}}
         <div ng-click="$ctrl.onRemove({contact: c})">Remove</div>
       </div>`,
    bindings: {
      contacts: '<',
      onRemove: '&'
    },
    controller: function() {}
  })

I use this component multiple times within my app. And the onRemove callback can behave differently, depending on where the contactList component is getting used. Example:

  • contactMainView (= component) displays a search bar and the resulting list of contacts using the contactList component. onRemove will delete the contact from the database.

  • groupMembersView displays all contacts belonging to the given group using the contactList component. Here it shouldn't be possible to remove a contact, though onRemove will not be set.


Ideas:

First I thought, that I could use an ng-if="$ctrl.onRemove" but that doesn't work, because onRemove is never undefined within contactList component. console.log(this.onRemove) always prints: function(locals) { return parentGet(scope, locals); }

Of course I could use another showRemove: '@' binding, but that doesn't look DRY to me.


Do you have any idea or some better solution to get things done?

Cosmin Ababei
  • 7,003
  • 2
  • 20
  • 34
Benjamin M
  • 23,599
  • 32
  • 121
  • 201

3 Answers3

22

The simplest way would to check if the attribute is defined. In your controller inject $attrs and then you can do:

if( $attrs.onRemove ) { //Do something }

Using the & binding angular will wrap the function in order to keep references to the original $scope of the passed method, even if is not defined.

Sebastian Sebald
  • 16,130
  • 5
  • 62
  • 66
0

Execute the function onRemove on component allow to get if a function was passed in parameter. So you can use ng-if="$ctrl.onRemove()"

component('contactList', {
template: 
  `<div ng-repeat="c in $ctrl.contacts">
     {{c.name}}
     <div ng-click="$ctrl.onRemove()({contact: c})" ng-if="$ctrl.onRemove()">Remove</div>
   </div>`,
bindings: {
  contacts: '<',
  onRemove: '&'
},
controller: function() {
  console.log(this.onRemove);
  console.log(this.onRemove());
}
})
Silvinus
  • 1,445
  • 8
  • 16
  • `console.log(this.onRemove());` throws an exception somewhere in the code when I pass some function to `on-remove="..."`, But it prints `undefined` when it's no defined. – Benjamin M Aug 12 '16 at 11:16
  • how to define a callback function binding please? – MartianMartian Sep 17 '16 at 08:30
  • Please see this post, it answerd to your question http://stackoverflow.com/questions/18378520/angularjs-pass-function-to-directive – Silvinus Sep 19 '16 at 06:53
0

another option is to define the callback as optional by adding a question mark in the binding definition: onRemove: '&?'

text from the documentation: All 4 kinds of bindings (@, =, <, and &) can be made optional by adding ? to the expression. The marker must come after the mode and before the attribute name. See the Invalid Isolate Scope Definition error for definition examples.

groetzi
  • 188
  • 1
  • 8