#1510 - Support for defining the selected value on HalFormsOptions.
We now expose a HalFormsOptions.withSelectedValue(…) and propagate this into the HAL FORMS property field named "value".
This commit is contained in:
@@ -23,6 +23,7 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
@@ -61,7 +62,7 @@ public interface HalFormsOptions {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
|
||||
return new Inline(values, null, null, null, null);
|
||||
return new Inline(values, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +75,7 @@ public interface HalFormsOptions {
|
||||
|
||||
Assert.notNull(link, "Link must not be null!");
|
||||
|
||||
return new Remote(link, null, null, null, null);
|
||||
return new Remote(link, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,14 +123,18 @@ public interface HalFormsOptions {
|
||||
@Nullable
|
||||
Long getMaxItems();
|
||||
|
||||
@Nullable
|
||||
Object getSelectedValue();
|
||||
|
||||
public static abstract class AbstractHalFormsOptions<T extends AbstractHalFormsOptions<T>>
|
||||
implements HalFormsOptions {
|
||||
|
||||
private final @Nullable String promptField, valueField;
|
||||
private final @Nullable Long minItems, maxItems;
|
||||
private final @Nullable Object selectedValue;
|
||||
|
||||
protected AbstractHalFormsOptions(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
|
||||
@Nullable Long maxItems) {
|
||||
@Nullable Long maxItems, @Nullable Object selectedValue) {
|
||||
|
||||
Assert.isTrue(minItems == null || minItems >= 0, "MinItems must be greater than or equal to 0!");
|
||||
|
||||
@@ -137,6 +142,7 @@ public interface HalFormsOptions {
|
||||
this.valueField = valueRef;
|
||||
this.minItems = minItems;
|
||||
this.maxItems = maxItems;
|
||||
this.selectedValue = selectedValue;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -179,6 +185,17 @@ public interface HalFormsOptions {
|
||||
return maxItems;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions#getSelectedValue()
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public Object getSelectedValue() {
|
||||
return selectedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the given field to be used as prompt field.
|
||||
*
|
||||
@@ -191,7 +208,7 @@ public interface HalFormsOptions {
|
||||
throw new IllegalArgumentException("Prompt field has to either be null or actually have text!");
|
||||
}
|
||||
|
||||
return with(promptField, valueField, minItems, maxItems);
|
||||
return with(promptField, valueField, minItems, maxItems, selectedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,7 +223,7 @@ public interface HalFormsOptions {
|
||||
throw new IllegalArgumentException("Value field has to either be null or actually have text!");
|
||||
}
|
||||
|
||||
return with(promptField, valueField, minItems, maxItems);
|
||||
return with(promptField, valueField, minItems, maxItems, selectedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +238,7 @@ public interface HalFormsOptions {
|
||||
throw new IllegalArgumentException("minItems has to be null or greater or equal to zero!");
|
||||
}
|
||||
|
||||
return with(promptField, valueField, minItems, maxItems);
|
||||
return with(promptField, valueField, minItems, maxItems, selectedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,13 +247,23 @@ public interface HalFormsOptions {
|
||||
* @param maxItems must be {@literal null} or greater than zero.
|
||||
* @return
|
||||
*/
|
||||
public T withMaxItems(Long maxItems) {
|
||||
public T withMaxItems(@Nullable Long maxItems) {
|
||||
|
||||
if (maxItems != null && maxItems <= 0) {
|
||||
throw new IllegalArgumentException("maxItems has to be null or greater than zero!");
|
||||
}
|
||||
|
||||
return with(promptField, valueField, minItems, maxItems);
|
||||
return with(promptField, valueField, minItems, maxItems, selectedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configured the value to be initially selected
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public T withSelectedValue(@Nullable Object value) {
|
||||
return with(promptField, valueField, minItems, maxItems, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,7 +276,7 @@ public interface HalFormsOptions {
|
||||
* @return
|
||||
*/
|
||||
protected abstract T with(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
|
||||
@Nullable Long maxItems);
|
||||
@Nullable Long maxItems, @Nullable Object selectedValue);
|
||||
}
|
||||
|
||||
public static class Inline extends AbstractHalFormsOptions<Inline> {
|
||||
@@ -262,9 +289,9 @@ public interface HalFormsOptions {
|
||||
* @param valueRef
|
||||
*/
|
||||
private Inline(Collection<? extends Object> values, @Nullable String promptRef, @Nullable String valueRef,
|
||||
@Nullable Long minItems, @Nullable Long maxItems) {
|
||||
@Nullable Long minItems, @Nullable Long maxItems, @Nullable Object selectedValue) {
|
||||
|
||||
super(promptRef, valueRef, minItems, maxItems);
|
||||
super(promptRef, valueRef, minItems, maxItems, selectedValue);
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
|
||||
@@ -283,12 +310,12 @@ public interface HalFormsOptions {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.AbstractHalFormsOptions#with(java.lang.String, java.lang.String, java.lang.Long, java.lang.Long)
|
||||
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.AbstractHalFormsOptions#with(java.lang.String, java.lang.String, java.lang.Long, java.lang.Long, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Inline with(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
|
||||
@Nullable Long maxItems) {
|
||||
return new Inline(inline, promptRef, valueRef, minItems, maxItems);
|
||||
@Nullable Long maxItems, @Nullable Object selectedValue) {
|
||||
return new Inline(inline, promptRef, valueRef, minItems, maxItems, selectedValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,9 +329,9 @@ public interface HalFormsOptions {
|
||||
private final Link link;
|
||||
|
||||
private Remote(Link link, @Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
|
||||
@Nullable Long maxItems) {
|
||||
@Nullable Long maxItems, @Nullable Object selectedValue) {
|
||||
|
||||
super(promptRef, valueRef, minItems, maxItems);
|
||||
super(promptRef, valueRef, minItems, maxItems, selectedValue);
|
||||
|
||||
Assert.notNull(link, "Link must not be null!");
|
||||
|
||||
@@ -323,12 +350,12 @@ public interface HalFormsOptions {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.Foo#withFoo(java.lang.String, java.lang.String)
|
||||
* @see org.springframework.hateoas.mediatype.hal.forms.HalFormsOptions.AbstractHalFormsOptions#with(java.lang.String, java.lang.String, java.lang.Long, java.lang.Long, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Remote with(@Nullable String promptRef, @Nullable String valueRef, @Nullable Long minItems,
|
||||
@Nullable Long maxItems) {
|
||||
return new Remote(link, promptRef, valueRef, minItems, maxItems);
|
||||
@Nullable Long maxItems, @Nullable Object selectedValue) {
|
||||
return new Remote(link, promptRef, valueRef, minItems, maxItems, selectedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
@JsonInclude(Include.NON_DEFAULT)
|
||||
final class HalFormsProperty implements Named {
|
||||
|
||||
private final String name, value, prompt, regex, placeholder;
|
||||
private final String name, prompt, regex, placeholder;
|
||||
private final Object value;
|
||||
private final boolean templated, multi;
|
||||
private final @JsonInclude(Include.NON_DEFAULT) boolean readOnly, required;
|
||||
private final @Nullable Long min, max, minLength, maxLength;
|
||||
@@ -64,12 +65,13 @@ final class HalFormsProperty implements Named {
|
||||
this.options = null;
|
||||
}
|
||||
|
||||
private HalFormsProperty(String name, boolean readOnly, String value, String prompt, String regex, boolean templated,
|
||||
private HalFormsProperty(String name, boolean readOnly, @Nullable Object value, String prompt, String regex,
|
||||
boolean templated,
|
||||
boolean required, boolean multi, String placeholder, @Nullable Long min, @Nullable Long max,
|
||||
@Nullable Long minLength, @Nullable Long maxLength, @Nullable HtmlInputType type,
|
||||
@Nullable HalFormsOptions options) {
|
||||
|
||||
Assert.notNull(name, "name must not be null!");
|
||||
Assert.notNull(name, "Name must not be null!");
|
||||
|
||||
this.name = name;
|
||||
this.readOnly = readOnly;
|
||||
@@ -132,7 +134,7 @@ final class HalFormsProperty implements Named {
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
HalFormsProperty withValue(String value) {
|
||||
HalFormsProperty withValue(@Nullable Object value) {
|
||||
|
||||
return this.value == value ? this
|
||||
: new HalFormsProperty(this.name, this.readOnly, value, this.prompt, this.regex, this.templated, this.required,
|
||||
@@ -329,7 +331,7 @@ final class HalFormsProperty implements Named {
|
||||
}
|
||||
|
||||
@JsonProperty
|
||||
String getValue() {
|
||||
Object getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,12 +80,13 @@ class HalFormsPropertyFactory {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
HalFormsOptionsFactory options = configuration.getOptionsFactory();
|
||||
HalFormsOptionsFactory optionsFactory = configuration.getOptionsFactory();
|
||||
|
||||
return model.createProperties((payload, metadata) -> {
|
||||
|
||||
String inputTypeSource = metadata.getInputType();
|
||||
HtmlInputType inputType = inputTypeSource == null ? null : HtmlInputType.of(inputTypeSource);
|
||||
HalFormsOptions options = optionsFactory.getOptions(payload, metadata);
|
||||
|
||||
HalFormsProperty property = new HalFormsProperty()
|
||||
.withName(metadata.getName())
|
||||
@@ -97,7 +98,8 @@ class HalFormsPropertyFactory {
|
||||
.withMaxLength(metadata.getMaxLength())
|
||||
.withRegex(lookupRegex(metadata)) //
|
||||
.withType(inputType) //
|
||||
.withOptions(options.getOptions(payload, metadata));
|
||||
.withValue(options != null ? options.getSelectedValue() : null) //
|
||||
.withOptions(options);
|
||||
|
||||
Function<String, I18nedPropertyMetadata> factory = I18nedPropertyMetadata.factory(payload, property);
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ class HalFormsTemplateBuilderUnitTest {
|
||||
}
|
||||
|
||||
@Test // #1483
|
||||
void rendersRegisteredSuggest() {
|
||||
void rendersInlineOptions() {
|
||||
|
||||
List<String> values = Arrays.asList("1234123412341234", "4321432143214321");
|
||||
|
||||
@@ -182,6 +182,30 @@ class HalFormsTemplateBuilderUnitTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test // #1510
|
||||
void propagatesSelectedValueToProperty() {
|
||||
|
||||
String selected = "1234123412341234";
|
||||
List<String> values = Arrays.asList(selected, "4321432143214321");
|
||||
|
||||
HalFormsConfiguration configuration = new HalFormsConfiguration()
|
||||
.withOptions(PatternExample.class, "number",
|
||||
metadata -> HalFormsOptions.inline(values).withSelectedValue(selected));
|
||||
|
||||
RepresentationModel<?> models = new RepresentationModel<>(
|
||||
Affordances.of(Link.of("/example", LinkRelation.of("create")))
|
||||
.afford(HttpMethod.POST)
|
||||
.withInput(PatternExample.class)
|
||||
.toLink());
|
||||
|
||||
Map<String, HalFormsTemplate> templates = new HalFormsTemplateBuilder(configuration, MessageResolver.DEFAULTS_ONLY)
|
||||
.findTemplates(models);
|
||||
|
||||
assertThat(templates.get("default").getPropertyByName("number")).hasValueSatisfying(it -> {
|
||||
assertThat(it.getValue()).isEqualTo(selected);
|
||||
});
|
||||
}
|
||||
|
||||
@Getter
|
||||
static class PatternExample extends RepresentationModel<PatternExample> {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user