-
Notifications
You must be signed in to change notification settings - Fork 334
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
Allow for booleans and numbers to be passed via data attributes #2832
Comments
I can think of a couple of different ways we could approach this… Option 1: If it looks like a duck, and quacks like a duck…Minic what Bootstrap does by testing for specific cases, e.g. the string 'true' or 'false', or a number that can be parsed into something that's equivalent to its string value. This is the simpler option but means we're always normalising based on what the user has passed to us, rather than what we actually expect / want. Option 2: Convert based on the types of the default optionsThis feels like a 'stricter' option, but is possibly at odds with the way merge configs currently works? This might also get tricky if we want 'nullable' options – for example the character count currently has This is roughly how I think this could work: // purely for example
function convertToType(value, type) {
switch (type) {
case 'string':
return value
// could potentially cater for 'boolean' data attributes e.g `<button data-prevent-double-click>` with this approach
case 'boolean':
if (value === 'true') {
return true
} else if (value === 'false') {
return false
} else {
return Boolean(value)
}
case 'number':
return Number(value)
default:
return value
}
}
function normaliseDataset(dataset, defaultConfig) {
for (var key in dataset) {
dataset[key] = convertToType(
dataset[key],
typeof defaultConfig[key]
)
}
return dataset
}
function MyComponent($module, config) {
var defaultConfig = {
points: 100,
isAwesome: true
}
this.config = mergeConfigs(
defaultConfig,
config,
normaliseDataset($module.dataset, defaultConfig)
)
} |
I was thinking of a different approach for this where the component would explicitely declare how it needs parsing for some attributes. This has the advantage of:
|
Another question, is whether we normalise only the element's |
I think if we opted for that sort of approach it'd be useful to keep the 'config config' (!) in one place, rather than having some of it in class-level variables and some of it passed to Something like: function MyComponent($module, config) {
var defaultConfig = {
points: {
type: 'number',
default: 100
},
isAwesome: {
type: 'boolean',
default: true
}
}
} This would be particularly useful if we do end up moving to components inheriting from a base component that takes care of the config merging for us, as we'll want a single place to determine how the config should work. This does however feel like it's starting to become quite complicated considering currently parts of it will need to be duplicated across every component that takes config… Maybe we should optimise for the simplest option to allow us to handle the config in the components we have now, and revisit in 5.0? I guess that'd be option 1? 🦆 |
Alternatively, we can work around this for now by handling it at the component level, for example in the button component we'd need to do something like: if (config.preventDoubleClick === 'true' || config.preventDoubleClick === true) { Which is a little messy but might unblock #2808 and we can revisit later. |
I thought of grouping defining the type in the same hash as the default, like you describe. Indeed, it has quite a different impact on what needs to be updated, so left it out (should probably have mentioned it as "a route we should probably not take for now"). I think it'd be a great pattern to have if we move to a base component, though. The method I was proposing felt like a step that would need to happen before that and we could take now. I can understand the clunkiness of having defaults in one place, parsing in another though. Regarding that last solution, both the Button and the CharacterCount each have a very specific place where they access the attribute, and only one so it feels like a good idea to get us out for now. I guess it depends on how far ahead we see the update of components to using a base class vs. having new components come in that'd need some parsing. If we foreses a lot of parsing comin ahead, we'd likely want a specialized method. On that topic, it's worth noting that using defaults to get the types wouldn't work for the CharacterCount as it doesn't have any default A couple of thoughts while I read through:
|
For options/config did the #2736 JSON approach get ruled out? Input: JSON string from data attribute <div id="my-component" data-config='{ "points": 100, "default": true }'>
<!-- Example -->
</div> Output: JavaScript object with types const component = document.getElementById('module')
const config = JSON.parse(component.dataset.config)
console.log(config) // { points: 100, default: true } |
We touched on it briefly in #2736 (comment) but I think the biggest downsides were:
As flagged in the linked issue, Bootstrap now support this via |
What
Ensure that config passed by data attributes is typed sensibly for the way we want to use it.
Why
Attributes passed via data attributes will always be strings, but in some cases we want to be able to treat them as booleans or numbers.
For example:
data-prevent-double-click
on buttons which is a booleandata-maxlength
on the character count which is a numberWho needs to work on this
Developers
Who needs to review this
Developers
Done when
The text was updated successfully, but these errors were encountered: