Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unobserve attributes #3

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docs/src/pages/docs/api-reference/lifecycles/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This is invoked when an attribute from the `observedAttributes` list is added, c
removed. This could be useful to make network request for updating the data.

```javascript
onAttributeChanged(element, ({ name, current }) => {
const unsubscribe = onAttributeChanged(element, ({ name, current }) => {
if (name === 'userID') {
update(element, async () => {
return await api.getUser(current)
Expand Down Expand Up @@ -98,11 +98,12 @@ Function that will be perfomed when the element is disconnected.
## onAttributeChanged

```javascript
onAttributeChanged(element, callback)
onAttributeChanged(element, callback) => function
```

Add a callback to be performed when one of the attribute from the `observedAttributes`
list is added, changed or removed.
list is added, changed or removed. Returns an unsubscriber function which when called
removes the callback to get more updates of attribute changes.

##### Parameters

Expand Down
2 changes: 1 addition & 1 deletion lib/define.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const define = (
super();

this._initialized = false;
this.__handleAttributeChangedCallback__ = [];
this.__handleAttributeChangedCallback__ = new Set();
this.__handleConnectedCallback__ = [];
this.__handleDisconnectedCallback__ = [];
this.__currentState__ = undefined;
Expand Down
3 changes: 2 additions & 1 deletion lib/lifecycles/onAttributeChanged.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export default function onAttributeChanged(element, callback) {
element.__handleAttributeChangedCallback__.push(callback);
element.__handleAttributeChangedCallback__.add(callback);
return () => element.__handleAttributeChangedCallback__.delete(callback);
}
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
"release": "npm run build && npm run cp:package && npm run test:all && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish dist"
},
"author": "Henrique Limas <[email protected]>",
"keywords": ["osagai", "webcomponents", "functional-programming"],
"keywords": [
"osagai",
"webcomponents",
"functional-programming"
],
"license": "ISC",
"dependencies": {},
"devDependencies": {
Expand All @@ -27,11 +31,11 @@
"electric-cli": "^3.0.4",
"jasmine-core": "^3.3.0",
"jest": "^23.6.0",
"karma": "^4.0.0",
"karma": "^4.4.1",
"karma-chrome-launcher": "^2.2.0",
"karma-jasmine": "^2.0.1",
"karma-rollup-preprocessor": "^6.1.2",
"prettier": "1.15.3",
"karma-rollup-preprocessor": "^7.0.2",
"prettier": "^1.15.3",
"regenerator-runtime": "^0.13.1",
"rollup": "^0.67.3",
"rollup-plugin-commonjs": "^9.2.0",
Expand Down
69 changes: 69 additions & 0 deletions test/lifecycles/attributes.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import define from "../../lib/define";
import { onAttributeChanged } from "../../lib/lifecycles/index.js";

describe("onAttributeChange", function() {
beforeEach(() => {
const
Component = () => () => `<span>dummy text content</span>`;

Component.observedAttributes = ['foo'];
define("attribute-test-element", Component);

const
element = document.createElement("attribute-test-element");
element.setAttribute("foo", "init");
document.body.appendChild(element);
});

afterEach(() => {
document.querySelector('attribute-test-element').remove();
});

it("should call the callback with the assigned attribute value", (done) => {
const
element = document.querySelector('attribute-test-element');

onAttributeChanged(element, ({name, current, old}) => {
if (name !== "foo") {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use a mock function and check if that function was called or not called in the other test. In that way the test will be simpler and we don't need to throw errors

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I don't get it 🤔. Could you describe it more?

done.fail(new Error(`"${name}" != "foo" wrong attribute name`));
}
else if (current !== "bar") {
done.fail(new Error(`"${current}" != "bar" wrong current value`));
}
else if (old !== "init") {
done.fail(new Error(`"${old}" != "init" wrong previous value`));
}
else {
done();
}
});

element.setAttribute("foo", "bar");
});

it("should not call the callback after it is unsubscribed", (done) => {
const
element = document.querySelector('attribute-test-element');

const
unsubscribe =
onAttributeChanged(element, ({current}) => {
if (current !== "first") {
done.fail(
new Error(`"${current}" !== "first", unexpected attribute value`)
);
}
else {
unsubscribe();
element.setAttribute("foo", "second");
setTimeout(done, 20);
}
});

element.setAttribute("foo", "first");

if (typeof unsubscribe !== "function") {
done.fail(new Error(`${typeof unsubscribe} != "function", return value is not an unsubscriber`));
}
});
});