Commit 50b0996b authored by Robert Knight's avatar Robert Knight

Allow function props to be invoked during a digest cycle

Allow function props passed to Preact components wrapped with
`wrapReactComponent` to be invoked when a digest cycle is already active
for some reason. In that case using `$scope.$apply` triggers an error.

This scenario is rare, as callbacks are usually invoked in response to
events that happen outside of Angular, but changes made by Angular code
can indirectly cause Preact components to invoke callbacks. For example,
in layout effects which run at the end of a `render` call.
parent 1c80ed66
...@@ -203,6 +203,14 @@ describe('wrapReactComponent', () => { ...@@ -203,6 +203,14 @@ describe('wrapReactComponent', () => {
assert.calledWith(onDblClick, 1); assert.calledWith(onDblClick, 1);
}); });
it('supports invoking callback properties if a digest cycle is already in progress', () => {
const { element, onDblClick } = renderButton();
element.scope.$apply(() => {
lastOnDblClickCallback({ count: 1 });
});
assert.calledWith(onDblClick, 1);
});
it('triggers a digest cycle when invoking callback properties', () => { it('triggers a digest cycle when invoking callback properties', () => {
// Create an Angular component which passes an `on-{event}` callback down // Create an Angular component which passes an `on-{event}` callback down
// to a child React component. // to a child React component.
......
...@@ -45,9 +45,20 @@ class ReactController { ...@@ -45,9 +45,20 @@ class ReactController {
`Was passed "${arg}"` `Was passed "${arg}"`
); );
} }
// Test whether a digest cycle is already in progress using `$$phase`,
// in which case there is no need to trigger one with `$apply`.
//
// Most of the time there will be no digest cycle in progress, but this
// can happen if a change made by Angular code indirectly causes a
// component to call a function prop.
if ($scope.$root.$$phase) {
this[propName](arg);
} else {
$scope.$apply(() => { $scope.$apply(() => {
this[propName](arg); this[propName](arg);
}); });
}
}; };
}); });
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment