Skip to content

Commit a70d1cd

Browse files
committed
Allow programmatic control of observation
Add a named new argument, `isObserving`, with a default value of `true`, which users can pass to explicitly opt into or out of observing an element at a given time. This allows for a declarative invocation of the modifier itself based on tracked state, rather than having to handle it in the callback(s) passed to the modifier. Users can work around this today by only passing the `onEnter` or `onExit` callbacks conditionally: <div {{did-intersect onEnter=(if this.shouldDoSomething this.doSomething no-op) onExist=(if this.shouldDoSomething this.doSomethingElse no-op) }} > However, as this example shows, this is repetive (and potentially error- prone). The new functionality allows a less error-prone, less repetitive, more expressive approach: <div {{did-intersect isObserving=this.shouldDoSomething onEnter=this.doSomething onExit=this.doSomethingElse }} > Resolves #396
1 parent 7952156 commit a70d1cd

File tree

2 files changed

+67
-6
lines changed

2 files changed

+67
-6
lines changed

addon/modifiers/did-intersect.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,14 @@ export default class DidIntersectModifier extends Modifier {
7777
return;
7878
}
7979

80-
let { onEnter, onExit, maxEnter, maxExit, options } = this.args.named;
80+
let {
81+
onEnter,
82+
onExit,
83+
maxEnter,
84+
maxExit,
85+
options,
86+
isObserving = true,
87+
} = this.args.named;
8188

8289
assert('onEnter or/and onExit is required', onEnter || onExit);
8390

@@ -161,7 +168,11 @@ export default class DidIntersectModifier extends Modifier {
161168
this._options = options;
162169
}
163170

164-
this.observe();
171+
if (isObserving) {
172+
this.observe();
173+
} else {
174+
this.unobserve();
175+
}
165176
}
166177

167178
// Move to willDestroy when we want to drop support for versions below ember-modifier 2.x

tests/integration/modifiers/did-intersect-test.js

+54-4
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,21 @@ module('Integration | Modifier | did-intersect', function (hooks) {
1616
this._admin = {};
1717
}
1818

19-
observe = sinon.stub();
20-
unobserve = sinon.stub();
19+
observe = sinon.stub().callsFake(() => {
20+
this.isObserving = true;
21+
});
22+
unobserve = sinon.stub().callsFake(() => {
23+
this.isObserving = false;
24+
});
2125
addEnterCallback = sinon.stub().callsFake((element, callback) => {
22-
this.onEnterCallback = sinon.spy(callback);
26+
this.onEnterCallback = sinon.spy(() => {
27+
if (this.isObserving) callback();
28+
});
2329
});
2430
addExitCallback = sinon.stub().callsFake((element, callback) => {
25-
this.onExitCallback = sinon.spy(callback);
31+
this.onExitCallback = sinon.spy(() => {
32+
if (this.isObserving) callback();
33+
});
2634
});
2735
}
2836

@@ -344,4 +352,46 @@ module('Integration | Modifier | did-intersect', function (hooks) {
344352

345353
assert.equal(this.newExitStub.callCount, 1, 'new exit callback is called');
346354
});
355+
356+
module('modifier accepts `isObserving` argument', function () {
357+
test('with a truth(y) value', async function (assert) {
358+
assert.expect(2);
359+
360+
await render(hbs`
361+
<div
362+
{{did-intersect
363+
isObserving=true
364+
onEnter=this.enterStub
365+
onExit=this.exitStub
366+
}}
367+
></div>
368+
`);
369+
370+
this.observerManagerMock.onEnterCallback();
371+
this.observerManagerMock.onExitCallback();
372+
373+
assert.ok(this.enterStub.calledOnce, 'the enter callback is invoked');
374+
assert.ok(this.exitStub.calledOnce, 'the onExit callback is invoked');
375+
});
376+
377+
test('with a false(y) value', async function (assert) {
378+
assert.expect(2);
379+
380+
await render(hbs`
381+
<div
382+
{{did-intersect
383+
isObserving=false
384+
onEnter=this.enterStub
385+
onExit=this.exitStub
386+
}}
387+
></div>
388+
`);
389+
390+
this.observerManagerMock.onEnterCallback();
391+
this.observerManagerMock.onExitCallback();
392+
393+
assert.ok(this.enterStub.notCalled, 'the enter callback is not invoked');
394+
assert.ok(this.exitStub.notCalled, 'the onExit callback is not invoked');
395+
});
396+
});
347397
});

0 commit comments

Comments
 (0)