update method

  1. @override
void update(
  1. String? id,
  2. String? classes,
  3. Map<String, String>? styles,
  4. Map<String, String>? attributes,
  5. Map<String, EventCallback>? events,
)
override

Implementation

@override
void update(
  String? id,
  String? classes,
  Map<String, String>? styles,
  Map<String, String>? attributes,
  Map<String, EventCallback>? events,
) {
  late Set<String> attributesToRemove;

  attributesToRemove = {};
  for (var i = 0; i < node.attributes.length; i++) {
    attributesToRemove.add(node.attributes.item(i)!.name);
  }

  node.clearOrSetAttribute('id', id);
  node.clearOrSetAttribute('class', classes == null || classes.isEmpty ? null : classes);
  node.clearOrSetAttribute(
    'style',
    styles == null || styles.isEmpty ? null : styles.entries.map((e) => '${e.key}: ${e.value}').join('; '),
  );

  if (attributes != null && attributes.isNotEmpty) {
    for (final attr in attributes.entries) {
      if (attr.key == 'value' && node.isHtmlInputElement) {
        if ((node as web.HTMLInputElement).value != attr.value) {
          if (kVerboseMode) {
            print("Set input value: ${attr.value}");
          }
          (node as web.HTMLInputElement).value = attr.value;
        }
        continue;
      }

      if (attr.key == 'checked' &&
          node.isHtmlInputElement &&
          ['checkbox', 'radio'].contains((node as web.HTMLInputElement).type)) {
        final shouldBeChecked = attr.value == 'true';
        if ((node as web.HTMLInputElement).checked != shouldBeChecked) {
          if (kVerboseMode) {
            print("Set input checked: $shouldBeChecked");
          }
          (node as web.HTMLInputElement).checked = shouldBeChecked;
          if (!shouldBeChecked && node.hasAttribute('checked')) {
            // Remove the attribute if unchecked to avoid HTML5 validation issues.
            node.removeAttribute('checked');
          }
        }
        continue;
      }

      if (attr.key == 'indeterminate' &&
          node.isHtmlInputElement &&
          (node as web.HTMLInputElement).type == 'checkbox') {
        final shouldBeIndeterminate = attr.value == 'true';
        if ((node as web.HTMLInputElement).indeterminate != shouldBeIndeterminate) {
          if (kVerboseMode) {
            print("Set input indeterminate: $shouldBeIndeterminate");
          }
          (node as web.HTMLInputElement).indeterminate = shouldBeIndeterminate;
          if (!shouldBeIndeterminate && node.hasAttribute('indeterminate')) {
            // Remove the attribute if unchecked to avoid HTML5 validation issues.
            node.removeAttribute('indeterminate');
          }
        }
        continue;
      }

      if (attr.key == 'value' && node.isHtmlSelectElement) {
        if ((node as web.HTMLSelectElement).value != attr.value) {
          if (kVerboseMode) {
            print("Set select value: ${attr.value}");
          }
          (node as web.HTMLSelectElement).value = attr.value;
        }
        continue;
      }

      node.clearOrSetAttribute(attr.key, attr.value);
    }
  }

  attributesToRemove.removeAll(['id', 'class', 'style', ...?attributes?.keys]);
  if (attributesToRemove.isNotEmpty) {
    for (final name in attributesToRemove) {
      node.removeAttribute(name);
      if (kVerboseMode) {
        print("Remove attribute: $name");
      }
    }
  }

  if (events != null && events.isNotEmpty) {
    final prevEventTypes = this.events?.keys.toSet();
    this.events ??= <String, EventBinding>{};
    final dataEvents = this.events!;
    events.forEach((type, fn) {
      prevEventTypes?.remove(type);
      final currentBinding = dataEvents[type];
      if (currentBinding != null) {
        currentBinding.fn = fn;
      } else {
        dataEvents[type] = EventBinding(node, type, fn);
      }
    });
    prevEventTypes?.forEach((type) {
      dataEvents.remove(type)?.clear();
    });
  } else {
    this.events?.forEach((type, binding) {
      binding.clear();
    });
    this.events = null;
  }
}