Multi-Level Component Callbacks in Angular 1.5
Asked Answered
P

1

6

I am coming from a React / Redux mindset where data-manipulation functions as well as data are passed from parent to child to grandchild etc. Components themselves do not modify data, rather they pass their intentions back up the component tree.

I am trying to replicate this with components in Angular 1.5. Consider the following:

app.js:

const appController = ($scope, data) => {
  $scope.doSomething = () => console.log('Foooooo!');
};

app.html:

<div>
  <node
    do-something="doSomething()"
  ></node>
</div>

node.js:

app.component('node', {
  // ...
  bindings: {
    doSomething: '&',
  },
});

node.html:

<div>
  <leaf
    do-something="$ctrl.doSomething()"
  ></leaf>
</div>

leaf.js:

app.component('leaf', {
  // ...
  bindings: {
    doSomething: '&',
  },
});

leaf.html:

<div ng-click="$ctrl.doSomething()"></div>

This works. When the div in leaf is clicked 'Foooooo!' is logged to the console. However, if I change the ngClick callback to pass in something in scope for leaf (or even just a literal such as 'foo') and change doSomething in app.js to take an argument that argument is undefined. My guess is that I have to somehow pass the data along in node, but I don't know how. Is there a way to pass arguments along intermediary components without having to write wrapper functions in scope? I've tried using arguments but that doesn't work -- is there some Angular way to accomplish what I want?

EDIT:

Plunkr: https://plnkr.co/edit/7L4Kd3rhJXoGlrHzecHf?p=preview

Panzer answered 9/5, 2016 at 17:39 Comment(5)
lol, node.js. That could get confusing. Also, a plunkr would be nice.Jeseniajesh
Try making your binding a reference instead of an expression, so instead of doSomething: '&' doSomething: '=' and remove the parentheses for the node and leaf markup.Jeseniajesh
could you add the code that you tried and isn't workingPest
A codepen would be very useful here. Everything you've described should work.Stelu
Added a plunkr: plnkr.co/edit/7L4Kd3rhJXoGlrHzecHf?p=previewPanzer
P
5

EDIT: This may or may not actually work...

It would appear as though when you call a function that was provided with the & operator that you are not calling the function directly, but rather calling a function which uses its argument as a sort of context for the expression. The following works:

app.js:

const appController = ($scope, data) => {
  $scope.doSomething = value => console.log(value);
};

app.html:

<div>
  <node
    do-something="doSomething(value)"
  ></node>
</div>

node.js:

app.component('node', {
  // ...
  bindings: {
    doSomething: '&',
  },
});

node.html:

<div>
  <leaf
    do-something="$ctrl.doSomething({ value: value })"
  ></leaf>
</div>

leaf.js:

app.component('leaf', {
  // ...
  bindings: {
    doSomething: '&',
  },
});

leaf.html:

<div ng-click="$ctrl.doSomething({ value: someVar })"></div>
Panzer answered 9/5, 2016 at 21:10 Comment(2)
KPthunder, want to add a working Plunkr and accept this answer for other?Cabasset
Turns out it doesn't actually work the way I thought it did. I come from a React background and I was trying to shoehorn a flux architecture in an Angular project but I wound up doing something different.Panzer

© 2022 - 2024 — McMap. All rights reserved.