diff --git a/README.md b/README.md index b9b6d9c..fe9660d 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,27 @@ The relative string is computed and updated in the browser by the underlying web For continuously-ticking elapsed displays use `Format.DURATION` or `Format.MICRO`. `Format.RELATIVE` (the default) collapses past times under a minute to "now". See [SPECIFICATIONS.md](SPECIFICATIONS.md) §2.8 for the full live-update behaviour matrix. +### Components without a value yet + +`new RelativeTime()` writes no `datetime` attribute and renders nothing until `setDateTime` is called. No default is applied: the current instant would be a value the caller did not choose, and it would keep ticking away from the intended one until that value arrives. + +Use the no-argument constructor when the value is not available at construction time. For an instance-reusing grid renderer: + +```java +grid.addColumn(new ComponentRenderer<>(RelativeTime::new, + (rt, task) -> rt.setDateTime(task.getCreated()))); +``` + +For a display that starts empty and is filled in from a listener: + +```java +RelativeTime preview = new RelativeTime().setFormatStyle(FormatStyle.LONG); +picker.addValueChangeListener(e -> preview.setDateTime(e.getValue())); +add(preview); +``` + +Call `clear()` to return the component to the empty state. + ## Special configuration when using Spring By default, Vaadin Flow only includes `com/vaadin/flow/component` to be always scanned for UI components and views. For this reason, the add-on might need to be allowed in order to display correctly. diff --git a/SPECIFICATIONS.md b/SPECIFICATIONS.md index 014a5ca..8749a67 100644 --- a/SPECIFICATIONS.md +++ b/SPECIFICATIONS.md @@ -119,7 +119,8 @@ The cadence depends on the displayed unit: ### 3.1 Construction ```java -// Empty: datetime can be set later +// No datetime: renders nothing until setDateTime is called. Intended for component +// renderers, asynchronously loaded values, and displays that start empty. RelativeTime rt = new RelativeTime(); add(rt); @@ -133,7 +134,7 @@ add(new RelativeTime(LocalDate.of(2025, 1, 1))); ```java public class RelativeTime extends Component { // HasStyle inherited from Component - public RelativeTime(); // empty; datetime can be set later + public RelativeTime(); // no datetime; renders nothing until set public RelativeTime(Instant datetime); public RelativeTime(OffsetDateTime datetime); public RelativeTime(ZonedDateTime datetime); @@ -199,7 +200,7 @@ When no configuration is applied: - `time-zone` is unset, so absolute-date output uses the viewer's browser default zone. - The `title` attribute is set automatically to the absolute formatted date and is surfaced as a native tooltip. - The element auto-updates on its own timer; no polling code is needed on the Java side. -- `RelativeTime` with no `datetime` set renders as an empty inline element. +- `RelativeTime` with no `datetime` set renders as an empty inline element. No default datetime is applied; see §3.1. ## 5. Theming diff --git a/src/main/java/com/flowingcode/vaadin/addons/relativetime/RelativeTime.java b/src/main/java/com/flowingcode/vaadin/addons/relativetime/RelativeTime.java index c990a3f..2a0dc9a 100644 --- a/src/main/java/com/flowingcode/vaadin/addons/relativetime/RelativeTime.java +++ b/src/main/java/com/flowingcode/vaadin/addons/relativetime/RelativeTime.java @@ -49,6 +49,10 @@ * the server's. There is no server-side API to read the displayed string; the string lives only * in the DOM. * + *
Empty state. A component with no target datetime renders nothing: the underlying + * element has no text to show. This applies to the {@linkplain #RelativeTime() no-argument + * constructor} and to {@link #clear()}. See the constructor for the cases it serves. + * *
Attributes, not properties. Setters write HTML attributes * ({@code setAttribute}), not DOM properties, because the upstream element is * attribute-driven and its kebab-case attribute names match the upstream docs @@ -94,7 +98,17 @@ public class RelativeTime extends Component { private Instant lastDateTime; - /** Creates an empty component. {@link #setDateTime} can be called later. */ + /** + * Creates a relative time component without a target datetime. Renders nothing until + * {@link #setDateTime} is called. + * + *
Use this constructor when the datetime is unavailable at creation, such as in component + * renderers ({@code new ComponentRenderer<>(RelativeTime::new, ...)}), asynchronous data + * loading, or displays reset via {@link #clear()}. + * + *
No default datetime is applied. The current instant would be a value the caller did not + * choose, and it would keep ticking away from the intended one until that value arrives. + */ public RelativeTime() {} /** Creates a component bound to the given instant. */ diff --git a/src/test/java/com/flowingcode/vaadin/addons/relativetime/UseCasesDemo.java b/src/test/java/com/flowingcode/vaadin/addons/relativetime/UseCasesDemo.java index 141c281..1623dc9 100644 --- a/src/test/java/com/flowingcode/vaadin/addons/relativetime/UseCasesDemo.java +++ b/src/test/java/com/flowingcode/vaadin/addons/relativetime/UseCasesDemo.java @@ -96,8 +96,10 @@ public UseCasesDemo() { addUseCase(layout, "stopwatch", "Live stopwatch", buildStopwatch(), "A running counter using Format.DURATION (ticks every second from 0s with no \"now\"" - + " plateau). The Start button pins the datetime to now; Stop clears it. Pattern:" - + " timers for in-progress work, build/deploy status, \"uptime since\" indicators."); + + " plateau). Built with the no-argument constructor, so it renders nothing until" + + " Start pins the datetime to now; Stop clears it and it goes back to empty." + + " Pattern: timers for in-progress work, build/deploy status, \"uptime since\"" + + " indicators."); addUseCase(layout, "session-expiry", "Session expiry warning", buildSessionWarning(),