-
Notifications
You must be signed in to change notification settings - Fork 319
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
Changes property options to support converter
#369
Conversation
Fixes #264 Changes `type` to be only a hint to the `converter` option which has the previous `type` functionality, an object with `toAttribute` and `fromAttribute` or just a function which is `fromAttribute`. In addition to the `value` these functions now also get the property's `type`. Also provides a default converter that supports `Boolean`, `String`, `Number`, `Object`, and `Array` out of the box. In addition, numbers and strings now become `null` if their reflected attribute is removed.
README.md
Outdated
keys. | ||
* `type`: Indicates the type of the property. This is used only as a hint for the | ||
`converter` to determine how to serialize and deserialize the attribute | ||
to/from a property. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add:
Default converters are provided for
String
,Number
, ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added to converter
section.
src/lib/updating-element.ts
Outdated
return value ? '' : null; | ||
case Object: | ||
case Array: | ||
return JSON.stringify(value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on experience with this being a footgun for users, consider anything better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this #375 to ensure this is well documented.
src/lib/updating-element.ts
Outdated
return value; | ||
} | ||
// Note: special case `Boolean` so users can use it as a `type`. | ||
const converter = options && options.converter || defaultConverter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't need a null check since there's a defaultPropertyDeclaration
?
Remove superfluous null checks
Previously, when an attribute changed as a result of a reflecting property changing, the property was prevented from mutating again as can happen when a custom `converter` is used. Now, the oppose is also true. When a property changes as a result of an attribute changing, the attribute is prevented from mutating again This change helps ensure that when a user calls `setAttribute`, a `converter.toAttribute` does not cause the attribute to immediately mutate. This is unexpected behavior and this change discourages it.
README.md
Outdated
`converter` to determine how to serialize and deserialize the attribute | ||
to/from a property. Note, when a property changes and the converter is used | ||
to update the attribute, the property is never updated again as a result of | ||
the attribute changing, and visa versa. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the attribute changing, and visa versa. | |
the attribute changing, and vice versa. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/lib/updating-element.ts
Outdated
@@ -15,27 +15,28 @@ | |||
/** | |||
* Converts property values to and from attribute values. | |||
*/ | |||
export interface AttributeSerializer<T = any> { | |||
export interface ComplexAttributeConverter<Type = any, TypeHint = any> { | |||
|
|||
/** | |||
* Deserializing function called to convert an attribute value to a property |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO Deserializing
and Deserializing
is a confusing terminology.
Is it still needed after this change ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
README.md
Outdated
`converter` to determine how to serialize and deserialize the attribute | ||
to/from a property. Note, when a property changes and the converter is used | ||
to update the attribute, the property is never updated again as a result of | ||
the attribute changing, and visa versa. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docs/_guide/properties.md
should also be updated, see #370
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this #375 to ensure this is well documented.
@@ -416,41 +446,44 @@ export abstract class UpdatingElement extends HTMLElement { | |||
name: PropertyKey, value: unknown, | |||
options: PropertyDeclaration = defaultPropertyDeclaration) { | |||
const ctor = (this.constructor as typeof UpdatingElement); | |||
const attrValue = ctor._propertyValueToAttribute(value, options); | |||
if (attrValue !== undefined) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this removed for a reason? Apparently undefined
was being used as a sentinel return value from toAttribute
meaning "no change". Should we keep this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done and added test.
src/lib/updating-element.ts
Outdated
if (options.reflect === true) { | ||
// Add to reflecting properties set if `reflect` is true and the property | ||
// is not reflecting from the attribute | ||
if (options.reflect === true && !(this._updateState & STATE_IS_REFLECTING)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be nice to separate STATE_IS_REFLECTING_TO_ATTRIBUTE
and STATE_IS_REFLECTING_TO_PROPERTY
; I think they should be mutually exclusive timing-wise, but the setting/reading the flags are paired to two different use cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Ensure Object/Array properties respect `undefined` (no change to attribute) and `null` (remove attribute) values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Won't merge until Sauce service incident is resolved and tests pass.
Shouldn't numbers and strings become
|
Fixes #264
Changes
type
to be only a hint to theconverter
option which has the previoustype
functionality, an object withtoAttribute
andfromAttribute
or just a function which isfromAttribute
. In addition to thevalue
these functions now also get the property'stype
.Also provides a default converter that supports
Boolean
,String
,Number
,Object
, andArray
out of the box.In addition, numbers and strings now become
null
if their reflected attribute is removed.