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

Changes property options to support converter #369

Merged
merged 15 commits into from
Dec 17, 2018
Merged

Conversation

sorvell
Copy link
Member

@sorvell sorvell commented Dec 13, 2018

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.

Steven Orvell added 3 commits December 13, 2018 10:07
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.
@sorvell sorvell added this to the 1.0.0 milestone Dec 13, 2018
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.
Copy link
Member

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, ...

Copy link
Member Author

Choose a reason for hiding this comment

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

Added to converter section.

return value ? '' : null;
case Object:
case Array:
return JSON.stringify(value);
Copy link
Member

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?

Copy link
Member Author

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.

return value;
}
// Note: special case `Boolean` so users can use it as a `type`.
const converter = options && options.converter || defaultConverter;
Copy link
Member

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?

Steven Orvell added 3 commits December 14, 2018 10:06
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.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
the attribute changing, and visa versa.
the attribute changing, and vice versa.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

@@ -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
Copy link
Contributor

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 ?

Copy link
Member Author

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.
Copy link
Contributor

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

Copy link
Member Author

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) {
Copy link
Member

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?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done and added test.

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)) {
Copy link
Member

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.

Copy link
Member Author

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.
Copy link
Member

@kevinpschaaf kevinpschaaf left a 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.

@kevinpschaaf kevinpschaaf merged commit 47717a7 into master Dec 17, 2018
@carsonpowers
Copy link

In addition, numbers and strings now become null if their reflected attribute is removed.

Shouldn't numbers and strings become undefined if they are removed? Changing them to null means that defaults set by the component will now be bypassed:

function func(foo='bar'){
  console.log(foo);
}

func(null); // null
func(undefined); // 'bar'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Discussion: supported serializers out of the box
5 participants