You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2020/07/09 08:59:28 UTC

[myfaces-tobago] 04/09: working on QS-1295

This is an automated email from the ASF dual-hosted git repository.

weber pushed a commit to branch TOBAGO-1999_Select2
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit 58618886fefedc68dd2c877bccf55b5d598a5e53
Author: Volker Weber <v....@inexso.de>
AuthorDate: Fri Feb 14 09:56:48 2020 +0100

    working on QS-1295
---
 .../internal/component/UISelect2Component.java     |  3 --
 .../internal/util/UISelect2ComponentUtil.java      | 48 +++++++++++++++++++--
 .../apache/myfaces/tobago/model/SubmittedItem.java | 11 +++++
 .../tobago/example/demo/Select2Controller.java     | 49 ++++++++++++++++++++++
 .../content/25-select/00-select2/select2.xhtml     | 16 +++++++
 .../standard/tag/SelectManyBoxRenderer.java        |  1 +
 .../renderkit/html/util/HtmlRendererUtils.java     | 15 ++++++-
 7 files changed, 135 insertions(+), 8 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/UISelect2Component.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/UISelect2Component.java
index f7d456a..fc7291a 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/UISelect2Component.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/UISelect2Component.java
@@ -1,10 +1,7 @@
 package org.apache.myfaces.tobago.internal.component;
 
 import javax.faces.component.StateHelper;
-import javax.faces.component.UIComponent;
 import javax.faces.convert.Converter;
-import java.util.HashSet;
-import java.util.Map;
 
 public interface UISelect2Component {
 
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/UISelect2ComponentUtil.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/UISelect2ComponentUtil.java
index 539f559..758e05a 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/UISelect2ComponentUtil.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/UISelect2ComponentUtil.java
@@ -7,13 +7,20 @@ import org.apache.myfaces.tobago.internal.component.AbstractUISelectManyBox;
 import org.apache.myfaces.tobago.internal.component.AbstractUISuggest;
 import org.apache.myfaces.tobago.internal.component.UISelect2Component;
 import org.apache.myfaces.tobago.model.SelectItem;
+import org.apache.myfaces.tobago.model.SubmittedItem;
 import org.apache.myfaces.tobago.model.UICustomItemContainer;
 import org.apache.myfaces.tobago.util.SelectItemUtils;
 
 import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
 import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public class UISelect2ComponentUtil {
@@ -57,7 +64,7 @@ public class UISelect2ComponentUtil {
   public static void ensureCustomValue(
       FacesContext facesContext, UISelect2Component component, Object value, AbstractUISuggest suggest) {
 
-    if (!isInItemlist(facesContext, component, value)) {
+    if (!isInItemList(facesContext, component, value)) {
       javax.faces.model.SelectItem item = null;
       if (suggest != null) {
         item = suggest.getSelectItem(facesContext, value, component.getConverter());
@@ -72,7 +79,7 @@ public class UISelect2ComponentUtil {
     }
   }
 
-  private static boolean isInItemlist(FacesContext facesContext, UISelect2Component component, Object value) {
+  private static boolean isInItemList(FacesContext facesContext, UISelect2Component component, Object value) {
     LOG.trace("check for value = \"{}\"", value);
     Iterable<javax.faces.model.SelectItem> items
         = SelectItemUtils.getItemIterator(facesContext, (UIComponent) component);
@@ -119,7 +126,7 @@ public class UISelect2ComponentUtil {
       validCustomItemMap.clear();
       for (javax.faces.model.SelectItem selectItem : set) {
         LOG.trace("cleanup check = \"{}\"", selectItem.getValue());
-        if (!isInItemlist(facesContext, component, selectItem.getValue())) {
+        if (!isInItemList(facesContext, component, selectItem.getValue())) {
           LOG.trace("cleanup readd = \"{}\"", selectItem.getValue());
           validCustomItemMap.add(selectItem);
         }
@@ -127,4 +134,39 @@ public class UISelect2ComponentUtil {
     }
   }
 
+  public static Iterable<javax.faces.model.SelectItem> ensureSubmittedValues(FacesContext facesContext,
+      UIInput component, Iterable<javax.faces.model.SelectItem> items, String[] submittedValues) {
+    if (submittedValues == null || !(component instanceof UISelect2Component)) {
+      return items;
+    }
+    Converter converter = component.getConverter();
+    Map<String, javax.faces.model.SelectItem> optionValues = new HashMap<String, javax.faces.model.SelectItem>();
+    for (javax.faces.model.SelectItem item : items) {
+      if (converter != null) {
+        optionValues.put(converter.getAsString(facesContext, component, item.getValue()), item);
+      } else {
+        optionValues.put(item.getValue().toString(), item);
+      }
+    }
+
+
+    List<javax.faces.model.SelectItem> itemsToRender = new ArrayList<javax.faces.model.SelectItem>();
+    for (String submittedValue : submittedValues) {
+      if (optionValues.keySet().contains(submittedValue)) {
+        optionValues.remove(submittedValue);
+      } else {
+        itemsToRender.add(new SubmittedItem(submittedValue));
+      }
+    }
+    if (itemsToRender.isEmpty()) {
+      return items;
+    } else {
+      for (javax.faces.model.SelectItem item : items) {
+        if (optionValues.values().contains(item)) {
+          itemsToRender.add(item);
+        }
+      }
+      return itemsToRender;
+    }
+  }
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SubmittedItem.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SubmittedItem.java
new file mode 100644
index 0000000..8a51cca
--- /dev/null
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SubmittedItem.java
@@ -0,0 +1,11 @@
+package org.apache.myfaces.tobago.model;
+
+import org.apache.myfaces.tobago.context.Markup;
+
+public class SubmittedItem extends SelectItem {
+
+  public SubmittedItem(String value) {
+    super(value, value);
+    setMarkup(Markup.ERROR);
+  }
+}
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Select2Controller.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Select2Controller.java
index 6be927c..5217923 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Select2Controller.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Select2Controller.java
@@ -30,6 +30,8 @@ public class Select2Controller implements Serializable {
 
   private LocaleConverter localeConverter = new LocaleConverter();
 
+  private NumberConverter numberConverter = new NumberConverter();
+
   private String one2Value;
 
   private String one3Value;
@@ -38,6 +40,8 @@ public class Select2Controller implements Serializable {
 
   private List<Locale> many8Locales;
 
+  private List<Integer> many9Numbers;
+
   private List<String> many7Countries;
 
   private List<SelectItem> items;
@@ -145,6 +149,51 @@ public class Select2Controller implements Serializable {
     }
   }
 
+  public List<Integer> getMany9Numbers() {
+    LOG.warn("get many9Numbers = \"{}\"", many9Numbers);
+    return many9Numbers;
+  }
+
+  public void setMany9Numbers(List<Integer> many9Numbers) {
+    LOG.warn("set many9Numbers = \"{}\"", many9Numbers);
+    this.many9Numbers = many9Numbers;
+  }
+
+  public List<SelectItem> getMany9NumbersItems() {
+    if (many9Numbers != null && !many9Numbers.isEmpty()) {
+      List<SelectItem> items = new ArrayList<SelectItem>();
+      for (Integer number : many9Numbers) {
+        items.add(new SelectItem(number, Integer.toString(number)));
+      }
+      return items;
+    } else {
+      return Collections.emptyList();
+    }
+  }
+
+  public NumberConverter getNumberConverter() {
+    return numberConverter;
+  }
+
+  private class NumberConverter implements Converter {
+
+    public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
+      try {
+        return Integer.parseInt(value);
+      } catch (NumberFormatException e) {
+        throw new ConverterException(e.getMessage(), e);
+      }
+    }
+
+    public String getAsString(FacesContext context, UIComponent component, Object value) throws ConverterException {
+      try {
+        return Integer.toString((Integer) value);
+      } catch (Exception e) {
+        throw new ConverterException(e.getMessage(), e);
+      }
+    }
+  }
+
   private class LocaleConverter implements Converter {
 
     private Map<String, Locale> localeMap;
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/25-select/00-select2/select2.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/25-select/00-select2/select2.xhtml
index b113a85..f98b89e 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/25-select/00-select2/select2.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/25-select/00-select2/select2.xhtml
@@ -243,6 +243,22 @@
         </tc:selectManyBox>
 
       </tc:panel>
+
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="400px;1*" rows="45px"/>
+        </f:facet>
+
+        <tc:label value="Enter numbers" for="many_9"/>
+        <tc:selectManyBox id="many_9"
+                          placeholder="Enter numbers"
+                          allowCustom="true"
+                          converter="#{select2Controller.numberConverter}"
+                          value="#{select2Controller.many9Numbers}">
+          <tc:selectItems value="#{select2Controller.many9NumbersItems}"/>
+        </tc:selectManyBox>
+
+      </tc:panel>
     </tc:panel>
 
 
diff --git a/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/SelectManyBoxRenderer.java b/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/SelectManyBoxRenderer.java
index 3c202e8..6f466f1 100644
--- a/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/SelectManyBoxRenderer.java
+++ b/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/SelectManyBoxRenderer.java
@@ -90,6 +90,7 @@ public class SelectManyBoxRenderer extends SelectManyRendererBase {
     final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
     writer.startElement(HtmlElements.DIV, select);
     writer.writeStyleAttribute(style);
+    writer.writeClassAttribute(Classes.create(select, "container"));
     style.setTop(Measure.ZERO);
     style.setLeft(Measure.ZERO);
 
diff --git a/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/util/HtmlRendererUtils.java b/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/util/HtmlRendererUtils.java
index 38025c3..fab6cfa 100644
--- a/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/util/HtmlRendererUtils.java
+++ b/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/util/HtmlRendererUtils.java
@@ -30,10 +30,15 @@ import org.apache.myfaces.tobago.component.UISheet;
 import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.context.ResourceManagerUtils;
 import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.apache.myfaces.tobago.internal.component.AbstractUISelectMany;
+import org.apache.myfaces.tobago.internal.component.AbstractUISelectManyBox;
+import org.apache.myfaces.tobago.internal.component.UISelect2Component;
 import org.apache.myfaces.tobago.internal.util.Deprecation;
 import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
 import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.internal.util.UISelect2ComponentUtil;
 import org.apache.myfaces.tobago.internal.webapp.TobagoResponseWriterWrapper;
+import org.apache.myfaces.tobago.model.SubmittedItem;
 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
 import org.apache.myfaces.tobago.renderkit.css.Classes;
 import org.apache.myfaces.tobago.renderkit.css.Style;
@@ -399,7 +404,7 @@ public final class HtmlRendererUtils {
       throws IOException {
     renderSelectItems(component, items, values, null, onlySelected, writer, facesContext);
   }
-  public static void renderSelectItems(final UIInput component, final Iterable<SelectItem> items, final Object[] values,
+  public static void renderSelectItems(final UIInput component, Iterable<SelectItem> items, final Object[] values,
       final String[] submittedValues, final Boolean onlySelected, final TobagoResponseWriter writer,
       final FacesContext facesContext) throws IOException {
 
@@ -408,6 +413,7 @@ public final class HtmlRendererUtils {
       LOG.debug("values = '{}'", Arrays.toString(values));
       LOG.debug("submittedValues = '{}'", Arrays.toString(submittedValues));
     }
+    items = UISelect2ComponentUtil.ensureSubmittedValues(facesContext, component, items, submittedValues);
     for (final SelectItem item : items) {
       if (item instanceof SelectItemGroup) {
         writer.startElement(HtmlElements.OPTGROUP, null);
@@ -426,7 +432,12 @@ public final class HtmlRendererUtils {
         if (itemValue instanceof String && values != null && values.length > 0 && !(values[0] instanceof String)) {
           itemValue = ComponentUtils.getConvertedValue(facesContext, component, (String) itemValue);
         }
-        final String formattedValue = RenderUtils.getFormattedValue(facesContext, component, itemValue);
+        final String formattedValue;
+        if (item instanceof SubmittedItem) {
+          formattedValue = item.getLabel();
+        } else {
+          formattedValue = RenderUtils.getFormattedValue(facesContext, component, itemValue);
+        }
         boolean contains;
         if (submittedValues == null) {
           contains = RenderUtils.contains(values, itemValue);