@jsonAttr Decorator

Maps a property to an HTML attribute using JSON stringification / evaluation rules ("JSON‑lite").


Quick Start

import {jsonAttr} from '@exadel/esl/modules/esl-utils/decorators';

class SettingsPanel extends HTMLElement {
  // Will read the attribute value, evaluate (JSON‑like) or fall back to {}
  @jsonAttr({defaultValue: {theme: 'light', compact: false}})
  config!: {theme: string; compact: boolean};
}

// <settings-panel config='{"theme":"dark","compact":true}'></settings-panel>
// panel.config => {theme: 'dark', compact: true}
// Without attribute: panel.config => {theme: 'light', compact: false}

// Writing assigns JSON (object) => attribute updated (or removed if falsy/object empty as per internal rules)
panel.config = {theme: 'dark', compact: false};

What It Does Today (Summary)

Aspect Current Behavior (v5.x)
Mapping Attribute string ⇄ object (or null) via internal evaluation (evaluate) + JSON.stringify on set
Default defaultValue used only when attribute missing (not written to DOM)
Readonly readonly: true -> prevents setting; still parses attribute
data-* dataAttr: true -> uses data- prefixed name
Errors Malformed JSON/eval logs a warning, returns defaultValue

When to Use @jsonAttr vs @attr

Use @jsonAttr for conventional object mapping with default object semantics and no need for fine‑grained custom parsing yet. Use @attr with a custom parser/serializer (see attr.md) when you need:


Inheritance / Override Patterns

You can redeclare the property with @prop to freeze or replace default behavior:

class BaseCfg extends HTMLElement {
  @jsonAttr({defaultValue: {enabled: true}}) options!: {enabled: boolean};
}
class LockedCfg extends BaseCfg {
  @prop(Object.freeze({enabled: false}), {readonly: true}) override options!: {enabled: boolean};
}

(Overrides the dynamic attribute mapping with a fixed prototype value.)


Future Expansion (ESL v6.0.0+)

Planned improvements (subject to change):

Until then: keep payloads simple, valid JSON objects.


Caveats (Current Version)


Minimal API Reference

jsonAttr<T>(config?: {
  name?: string;
  readonly?: boolean;
  dataAttr?: boolean;
  defaultValue?: T; // used only if attribute is absent
}): PropertyDecorator;