Skip to content

Commit

Permalink
Fix update of checked property of checkbox input (#309)
Browse files Browse the repository at this point in the history
Resolve #287.

The `checked` attribute is a peculiar one, as any value on it keeps the checkbox checked. Attribute updates in `DOMRenderer` don't handle removals of attributes, but this seems to be the only case where this is relevant. I've added special handling for this attribute and checkbox inputs, and also had to declare `HTMLAttribute.checked` to set `isUpdatedAsProperty: true` on it for it to fully work.
  • Loading branch information
MaxDesiatov authored Nov 28, 2020
1 parent c754b31 commit dfcacc8
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 1 deletion.
13 changes: 13 additions & 0 deletions Sources/TokamakDOM/DOMNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,25 @@ extension AnyHTML {
// @carson-katri: For diffing, could you build a Set from the keys and values of the dictionary,
// then use the standard lib to get the difference?

// `checked` attribute on checkboxes is a special one as its value doesn't matter. We only
// need to check whether it exists or not, and set the property if it doesn't.
var containsChecked = false
for (attribute, value) in attributes {
if attribute.isUpdatedAsProperty {
dom.ref[dynamicMember: attribute.value] = .string(value)
} else {
_ = dom.ref.setAttribute!(attribute.value, value)
}

if attribute == .checked {
containsChecked = true
}
}

if !containsChecked && dom.ref.type == "checkbox" &&
dom.ref.tagName.string!.lowercased == "input"
{
dom.ref.checked = .boolean(false)
}

if let dynamicSelf = self as? AnyDynamicHTML {
Expand Down
2 changes: 1 addition & 1 deletion Sources/TokamakDOM/Styles/ToggleStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public struct CheckboxToggleStyle: ToggleStyle {
public func makeBody(configuration: ToggleStyleConfiguration) -> some View {
var attrs: [HTMLAttribute: String] = ["type": "checkbox"]
if configuration.isOn {
attrs["checked"] = "checked"
attrs[.checked] = "checked"
}
return HTML("label") {
DynamicHTML("input", attrs, listeners: [
Expand Down
2 changes: 2 additions & 0 deletions Sources/TokamakStaticHTML/Views/HTML.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public struct HTMLAttribute: Hashable {
}

public static let value = HTMLAttribute("value", isUpdatedAsProperty: true)

public static let checked = HTMLAttribute("checked", isUpdatedAsProperty: true)
}

extension HTMLAttribute: CustomStringConvertible {
Expand Down

0 comments on commit dfcacc8

Please # to comment.