-
Notifications
You must be signed in to change notification settings - Fork 601
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
String properties should be set to undefined
when the associated attribute is removed
#6630
Comments
…roperty (#1026) # Pull Request ## 🤨 Rationale After some discussion within the team, we decided that it would be best not to explicitly call out `null` as a possible value for `idFieldName` even though there are code paths that could cause it to be set to `null` (e.g. calling `table.removeAttribute('id-field-name')`). The rationale for this decision is that all our string attribute could technically be null and we don't want to call `null` out on all the types or have inconsistency in our typing. Instead, I created the following FAST issue: microsoft/fast#6630 ## 👩💻 Implementation - Remove `| null` from the type of `idFieldName` on the table - Modify the `TableValidator` class to handle `null` without explicitly checking for it. This is done using a `typeof idField !== 'string'` check now. ## 🧪 Testing - Ran auto tests - Manually tested in dev tools that calling `removeAttribute('id-field-name')` on the table does not cause a validation error ## ✅ Checklist <!--- Review the list and put an x in the boxes that apply or ~~strike through~~ around items that don't (along with an explanation). --> - [x] I have updated the project documentation to reflect my changes or determined no changes are needed.
Thanks @mollykreis for the issue and your patience. We aren't doing anything to manipulate the values on removal. I can confirm that I repro when an attribute is removed it's value is being set to null; however, I opened the console and grabbed a random native element from the GitHub DOM, removed a custom data-attribute which was set and then logged The above investigation just led me to double check the spec and I can confirm that null is to be expected here rather than undefined. From the spec:
|
@mollykreis - just wanted to follow up and see if you had thoughts on the above or if I'm good to close out given the above line from the spec. |
The concern our team is facing (thanks @mollykreis for creating this issue to track it) is about the JS property representation of HTML attributes not aligning with browser behavior for FAST components. The behavior of Specifically the same attribute state (an absent attribute) has multiple JS property representations (null or undefined). That is not common in DOM APIs. So for the // No attribute
let a = document.createElement('div');
a.getAttribute('data-test'); // null
a.dataset.test; //undefined <---
// Attribute set
a.setAttribute('data-test', 'foo');
a.getAttribute('data-test'); // 'foo'
a.dataset.test; // 'foo'
// Attribute removed
a.removeAttribute('data-test');
a.getAttribute('data-test'); // null
a.dataset.test; //undefined <--- Notice how in the above there is not an observable difference between an element with a What Molly's example shows is that FAST's behavior differs from the normal DOM behavior. To extend the example given: @customElement('cool-element')
class MyElement extends FoundationElement {
@attr({ attribute: 'my-cool-value' });
public myCoolValue?: string;
}
// No attribute
let a = document.createElement('cool-element');
a.getAttribute('my-cool-value'); // null
a.myCoolValue; //undefined <---
// Attribute set
a.setAttribute('my-cool-value', 'foo');
a.getAttribute('my-cool-value'); // 'foo'
a.myCoolValue; // 'foo'
// Attribute removed
a.removeAttribute('my-cool-value');
a.getAttribute('my-cool-value'); // null
a.myCoolValue; // null <--- unexpected JS representation of absent attribute, should match the initial representation, i.e. `undefined` Notice how in FAST there is an observable difference of the JS property between an element with an attribute that was never set and an element with the attribute removed. This is the unexpected behavior. JS properties synchronized to FAST attributes do not have a consistent mapping. The exact same attribute state (absence of the attribute) has multiple possible property states (can be either null or undefined) in FAST. That is not common in DOM APIs that reflect attributes to properties. |
@rajsite thanks - I'm going to tag in @EisenbergEffect here as well given I do not see where we are modifying this in the code. Forgive my confusion, I don't see where we're modifying this in the code. Perhaps you can share the link or perhaps @EisenbergEffect can find it. My point above is that the "Custom Element Reactions" spec specifically calls out this behavior for the
From what I can tell, any reflection is from the platform here or it could just be that I'm not seeing it. I don't see where we're changing the value on js property reflection in the element-controller code. If this is the platform, I'm not sure we can (or should) do anything about it. As far as I'm aware, the |
@chrisdholt is correct here. It's not that we're trying to do something different. The platform itself is telling us that the value is null. So, to "fix" this, we would have to internally map null values to undefined. But I don't think we can make that assumption on behalf of the programmer. It's possible that we could add some new mode to attribute reflection that did this. Have you all looked into whether you could handle this with a custom converter assigned to the attributes? If that works, you could even create your own decorator that wrapped ours and applied this behavior via your converter. |
🐛 Bug Report
When you have a string property that is associated with an attribute, removing the attribute from the element sets the property to
null
instead ofundefined
. However, the correct behavior would be setting the property toundefined
since that is the default value for a string.For example, consider an element defined as follows:
If the element is added to the DOM as
<my-element></my-element>
with no attributes set, interaction with the element would look like:This is loosely related to #5320 (comment)
💻 Repro or Code Sample
🤔 Expected Behavior
When an attribute is removed from an element derived from FoundationElement, the property associated with that attribute should be set to
undefined
.😯 Current Behavior
When you remove an attribute from an element derived from FoundationElement, the property associated with that attribute gets set to
null
rather than the default value ofundefined
. This leads to inconsistent behavior where the property's value starts asundefined
but adding and then removing an attribute changes the property's value tonull
.💁 Possible Solution
Currently the FAST element sets the property's value to the value passed to
attributeChangedCallback
. Instead, if thenewValue
isnull
, the property should be set toundefined
.🔦 Context
As shown above, I would like to define a property in an element as:
However, there are code paths within FAST that could cause
myCoolValue
to be set tonull
, which causes problems when trying to write strongly typed TypeScript code.Alternatively, I could define the property as:
The above would more accurately describe the possible values of
myCoolValue
, but I don't want to have to litter my code with| null
types. I also don't want the types in the custom elements I define to diverge too much from the types of the properties on FAST controls, the majority of which are typed asstring
.🌍 Your Environment
I don't think this is specific to a given environment, but I am using:
Edge Version 109.0.1518.78 (Official build) (64-bit)
The text was updated successfully, but these errors were encountered: