-
Notifications
You must be signed in to change notification settings - Fork 955
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
Using a directive in an attribute causes it to be marked dirty even if the final value is unchanged #890
Comments
Recently, I experienced the same issue. I have a custom directive and although the value of an attribute (the result of the directive) does not change, setAttribute is called by lit-html with the same value every time the template re-renders. The case I hit is with the img tag, if you use a directive (reproduces with the built-in ifDefined as well) with the "src", calling setAttribute on each rendering causes network request for the image (if cache is not present or cache expires). <img src="${myDirective(src)}" This is a quick hack, that seems to workaround the issue, but it must be a better way of fixing it. The directive below is the built-in ifDefined directive with few additional lines, that can be seen below. It checks if the value is changed and if not - sets "noChange". export const ifDefined = directive((value: unknown) => (part: Part) => {
if (value === undefined && part instanceof AttributePart) {
if (value !== part.value) {
const name = committer.name;
element.removeAttribute(name);
}
} else {
+ if (part.committer && part.committer.element && part.committer.element.getAttribute(part.committer.name) === value) {
+ part.setValue(noChange);
+ } else {
part.setValue(value);
+ }
}
}); |
This is a general gotcha with directives, but I'm not sure yet how to address this automatically in AttributePart, so the fix in ifDefined seems like a good intermediate fix. I'll make a PR. |
Non-breaking fixes for minor issues. * fixes lit-element/#722 * fixes lit-element/#890
Non-breaking fixes for minor issues. * fixes lit-element/#722 * fixes lit-element/#890
Description
The mechanism by which directives are "resolved" in AttributePart results in it erroneously marking a value as dirty as long as there is at least one level of directive "between" a template and the final output. This means that any attribute that is set to a directive is effectively always marked dirty and re-applied on every render.
Steps to Reproduce
Live Reproduction Link
https://stackblitz.com/edit/lit-html-thtgvg?file=src/index.js
Expected Results
No alert would be shown (maxlength would not be mutated the second time, as its underlying value hasn't actually been changed)
Actual Results
Alert is shown.
Browsers Affected
Additional Notes
This looks to me to be a problem with
AttributePart#setValue
, here: https://github.com/Polymer/lit-html/blob/master/src/lib/parts.ts#L113When a directive is set as the value, the template that contains the attribute calls
AttributePart.setValue
with the directive (thus changingthis.value
from the previous value of20
to a reference to the directive function). When the directive function is later resolved as part of the commit process,setValue
is called again with the result of the directive (still20
), but sincethis.value
is currently the directive and20
is a primitive that isn't equal to the directive, the AttributePart gets marked as dirty.The text was updated successfully, but these errors were encountered: