-
Notifications
You must be signed in to change notification settings - Fork 76
feat: add signal support for Details component summary text #8521
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |
| import com.vaadin.flow.component.ComponentEventListener; | ||
| import com.vaadin.flow.component.HasComponents; | ||
| import com.vaadin.flow.component.HasSize; | ||
| import com.vaadin.flow.component.SignalPropertySupport; | ||
| import com.vaadin.flow.component.Synchronize; | ||
| import com.vaadin.flow.component.Tag; | ||
| import com.vaadin.flow.component.dependency.JsModule; | ||
|
|
@@ -33,6 +34,7 @@ | |
| import com.vaadin.flow.component.shared.HasTooltip; | ||
| import com.vaadin.flow.component.shared.SlotUtils; | ||
| import com.vaadin.flow.shared.Registration; | ||
| import com.vaadin.signals.Signal; | ||
|
|
||
| /** | ||
| * Details is an expandable panel for showing and hiding content from the user | ||
|
|
@@ -61,6 +63,10 @@ public class Details extends Component implements HasComponents, HasSize, | |
| private final Component summaryContainer; | ||
| private final Div contentContainer; | ||
|
|
||
| /** Signal support for the summary text property. */ | ||
| private final SignalPropertySupport<String> summaryTextSupport = SignalPropertySupport | ||
| .create(this, this::updateSummaryText); | ||
|
|
||
| /** | ||
| * Server-side component for the {@code <vaadin-details-summary>} element. | ||
| */ | ||
|
|
@@ -81,7 +87,7 @@ public Details() { | |
| SlotUtils.addToSlot(this, "summary", summaryContainer); | ||
|
|
||
| if (getElement().getPropertyRaw("opened") == null) { | ||
| setOpened(false); | ||
| getElement().setProperty("opened", false); | ||
| } | ||
|
|
||
| getElement().addPropertyChangeListener("opened", event -> fireEvent( | ||
|
|
@@ -97,7 +103,10 @@ public Details() { | |
| */ | ||
| public Details(String summary) { | ||
| this(); | ||
| setSummaryText(summary); | ||
| if (summary == null) { | ||
| summary = ""; | ||
| } | ||
|
Comment on lines
+106
to
+108
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is also done for the other constructor that receives the summary as a String. Does it make sense to move it to the |
||
| updateSummaryText(summary); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -109,7 +118,19 @@ public Details(String summary) { | |
| */ | ||
| public Details(Component summary) { | ||
| this(); | ||
| setSummary(summary); | ||
| updateSummary(summary); | ||
| } | ||
|
|
||
| /** | ||
| * Initializes a new Details component with a summary text provided by a | ||
| * signal. | ||
| * | ||
| * @param summaryTextSignal | ||
| * the signal that provides the summary text | ||
| */ | ||
| public Details(Signal<String> summaryTextSignal) { | ||
| this(); | ||
| summaryTextSupport.bind(summaryTextSignal); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -125,8 +146,11 @@ public Details(Component summary) { | |
| */ | ||
| public Details(String summary, Component content) { | ||
| this(); | ||
| setSummaryText(summary); | ||
| add(content); | ||
| if (summary == null) { | ||
| summary = ""; | ||
| } | ||
| updateSummaryText(summary); | ||
| contentContainer.add(content); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -142,8 +166,23 @@ public Details(String summary, Component content) { | |
| */ | ||
| public Details(Component summary, Component content) { | ||
| this(); | ||
| setSummary(summary); | ||
| add(content); | ||
| updateSummary(summary); | ||
| contentContainer.add(content); | ||
| } | ||
|
|
||
| /** | ||
| * Initializes a new Details component with a summary text provided by a | ||
| * signal and content. | ||
| * | ||
| * @param summaryTextSignal | ||
| * the signal that provides the summary text. | ||
| * @param content | ||
| * the content component to add. | ||
| */ | ||
| public Details(Signal<String> summaryTextSignal, Component content) { | ||
| this(); | ||
| summaryTextSupport.bind(summaryTextSignal); | ||
| contentContainer.add(content); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -160,7 +199,7 @@ public Details(Component summary, Component content) { | |
| */ | ||
| public Details(String summary, Component... components) { | ||
| this(summary); | ||
| add(components); | ||
| contentContainer.add(components); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -177,7 +216,22 @@ public Details(String summary, Component... components) { | |
| */ | ||
| public Details(Component summary, Component... components) { | ||
| this(summary); | ||
| add(components); | ||
| contentContainer.add(components); | ||
| } | ||
|
|
||
| /** | ||
| * Initializes a new Details component with a summary text provided by a | ||
| * signal and optional content components. | ||
| * | ||
| * @param summaryTextSignal | ||
| * the signal that provides the summary text. | ||
| * @param components | ||
| * the content components to add. | ||
| */ | ||
| public Details(Signal<String> summaryTextSignal, Component... components) { | ||
| this(); | ||
| summaryTextSupport.bind(summaryTextSignal); | ||
| contentContainer.add(components); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -198,13 +252,7 @@ protected Component createSummaryContainer() { | |
| * any previously set summary | ||
| */ | ||
| public void setSummary(Component summary) { | ||
| summaryContainer.getElement().removeAllChildren(); | ||
| if (summary == null) { | ||
| return; | ||
| } | ||
|
|
||
| this.summary = summary; | ||
| summaryContainer.getElement().appendChild(summary.getElement()); | ||
| updateSummary(summary); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -218,14 +266,19 @@ public Component getSummary() { | |
| } | ||
|
|
||
| /** | ||
| * Creates a text wrapper and sets a summary via | ||
| * {@link #setSummary(Component)} | ||
| * Sets the summary text of the details component. | ||
| * | ||
| * @param summary | ||
| * the summary text to set, or {@code null} for empty text | ||
| * @throws com.vaadin.signals.BindingActiveException | ||
| * if the summary text is currently bound to a signal | ||
| * @see #bindSummaryText(Signal) | ||
| */ | ||
| public void setSummaryText(String summary) { | ||
| if (summary == null) { | ||
| summary = ""; | ||
| } | ||
| setSummary(new Span(summary)); | ||
| summaryTextSupport.set(summary); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -236,6 +289,54 @@ public String getSummaryText() { | |
| return summary == null ? "" : summary.getElement().getText(); | ||
| } | ||
|
|
||
| /** | ||
| * Updates the summary component. For internal use during initialization and | ||
| * signal updates. | ||
| */ | ||
| private void updateSummary(Component summary) { | ||
| summaryContainer.getElement().removeAllChildren(); | ||
| if (summary == null) { | ||
| return; | ||
| } | ||
|
|
||
| this.summary = summary; | ||
| summaryContainer.getElement().appendChild(summary.getElement()); | ||
| } | ||
|
|
||
| /** | ||
| * Updates the summary text when bound to a signal. | ||
| */ | ||
| private void updateSummaryText(String newText) { | ||
| if (summary == null || !(summary instanceof Span)) { | ||
| updateSummary(new Span(newText)); | ||
| } else { | ||
| summary.getElement().setText(newText); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not covered by any tests. |
||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Binds a signal to update the summary text of the details component. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For consistency public bind* methods should say same message all over. For this case |
||
| * <p> | ||
| * When bound, the signal manages the summary text. Any previously set | ||
| * custom summary component will be replaced when the signal updates. | ||
| * | ||
| * @param signal | ||
| * the signal that provides the new summary text, or {@code null} | ||
| * to remove the binding. | ||
| */ | ||
| public void bindSummaryText(Signal<String> signal) { | ||
| summaryTextSupport.bind(signal); | ||
| } | ||
|
|
||
| /** | ||
| * Gets the summary text signal support instance for testing purposes. | ||
| * | ||
| * @return the summary text signal support | ||
| */ | ||
| SignalPropertySupport<String> getSummaryTextSupport() { | ||
| return summaryTextSupport; | ||
| } | ||
|
|
||
| /** | ||
| * Adds components to the content section | ||
| * | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this change needed for the feature to work?