You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2019/04/16 10:32:55 UTC

[isis] branch master updated: ISIS-2001: generalizes the wicket viewer to support "dependent defaults"

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

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 2cea0ed  ISIS-2001: generalizes the wicket viewer to support "dependent defaults"
     new 1ffa8a4  Merge branch 'ISIS-2001'
2cea0ed is described below

commit 2cea0edd3320a8f7e29aab8f2d5a416716ca38f4
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Tue Apr 16 11:27:42 2019 +0100

    ISIS-2001: generalizes the wicket viewer to support "dependent defaults"
    
    Also, the Wicket viewer will automatically check that defaults are compatible with choices available for the argument (if any) and reset if required.
---
 .../rgcms/_rgcms_methods_prefixes_default.adoc     | 58 +++++++++++++++++++++-
 .../main/asciidoc/guides/ugvro/_ugvro_ro-spec.adoc |  3 +-
 .../spec/feature/ObjectActionParameter.java        |  4 +-
 .../specimpl/ObjectActionParameterAbstract.java    |  7 ++-
 .../domainobjects/ObjectActionReprRenderer.java    |  2 +-
 .../viewer/wicket/model/models/ScalarModel.java    | 34 ++++++++++++-
 .../components/actions/ActionParametersForm.java   | 32 ++++++------
 .../ui/components/scalars/PanelWithChoices.java    | 26 ----------
 .../components/scalars/ScalarPanelAbstract2.java   | 51 +++++++++++++++++++
 .../scalars/ScalarPanelSelect2Abstract.java        | 16 +++++-
 .../scalars/reference/ReferencePanel.java          |  3 +-
 .../valuechoices/ValueChoicesSelect2Panel.java     |  4 +-
 12 files changed, 184 insertions(+), 56 deletions(-)

diff --git a/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_methods_prefixes_default.adoc b/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_methods_prefixes_default.adoc
index 145d4fa..a52a91b 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_methods_prefixes_default.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgcms/_rgcms_methods_prefixes_default.adoc
@@ -75,8 +75,7 @@ public class UpdateCategoryContributions ... {
     public Categorized updateCategory(
             final Categorized item,                              // <1>
             final Category category,
-            @Parameter(optionality = Optionality.OPTIONAL)
-            final Subcategory subcategory) {
+            @Nullable final Subcategory subcategory) {
         item.setCategory(category);
         item.setSubcategory(subcategory);
         return item;
@@ -96,7 +95,62 @@ public class UpdateCategoryContributions ... {
 <3> defaults the 2-th parameter using the item's `subcategory` property
 
 
+=== Dependent Defaults
 
+Action parameters also support the notion of dependent defaults, whereby the value of a default is dependent upon the value of some other previous argument.
+
+In this example we can default the `gross` argument based on the previous `net` and `vat` arguments:
+
+[source,java]
+----
+public int add(final Integer net, final Integer vat, final Integer gross) {
+    return net + vat;
+}
+
+public Integer default2Add(final Integer net, final Integer val) {
+    if(net == null || val == null) { return null; }
+    return net + val;
+}
+----
+
+As a more complex example (taken from the (non-ASF) http://github.com/isisaddons/isis-app-kitchensink[Isis addons' kitchensink] app), we can default the NFL region from the NFL league, and then the NFL team based on the region:
+
+[source,java]
+----
+public NflPlayer updateUsingEntity(
+        final NflLeague league,
+        @Nullable final NflRegion region,
+        @Nullable final NflTeamEntity nflTeamEntity) {
+
+    setLeague(league);
+    setRegion(region);
+    setTeamEnum(NflTeamEnum.lookup(nflTeamEntity));
+    setTeamEntity(nflTeamEntity);
+
+    return this;
+}
+
+public List<NflRegion> choices1UpdateUsingEntity(final NflLeague league) {
+    return NflRegion.thoseFor(league);
+}
+public List<NflTeamEntity> choices2UpdateUsingEntity(final NflLeague league, final NflRegion region) {
+    return nflTeams.thoseFor(region);
+}
+public NflLeague default0UpdateUsingEntity() {
+    return getLeague();
+}
+public NflRegion default1UpdateUsingEntity(final NflLeague nflLeague) {
+    return choices1UpdateUsingEntity(nflLeague).stream()
+            .findFirst().orElse(null);
+}
+public NflTeamEntity default2UpdateUsingEntity(
+                                final NflLeague league, final NflRegion region) {
+    return choices2UpdateUsingEntity(league, region).stream()
+            .findFirst().orElse(null);
+}
+----
+
+In fact, in the example above the two `defaultNxxx` methods are not required; if a choices exists then the Wicket viewer will (now) ensure that the selected argument is compatible with the choices, and reset the argument to an empty value otherwise.
 
 
 == Properties
diff --git a/adocs/documentation/src/main/asciidoc/guides/ugvro/_ugvro_ro-spec.adoc b/adocs/documentation/src/main/asciidoc/guides/ugvro/_ugvro_ro-spec.adoc
index 59de91e..dd4d175 100644
--- a/adocs/documentation/src/main/asciidoc/guides/ugvro/_ugvro_ro-spec.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/ugvro/_ugvro_ro-spec.adoc
@@ -157,8 +157,7 @@ in the RO spec, the main point being to avoid the "N+1" problem of too many (slo
 this feature one can load a grid of data in a single call.  (That said, the xref:../ugvro/ugvro.adoc#_ugvro_simplified-representations[simplified representations]
 supported by Restful Objects viewer also support this use case, albeit in way that deviates from the RO spec).
 
-This link:https://www.youtube.com/watch?v=hSKnqqBQ7Zo[screencast] demonstrates the Restful Object viewer's support for `x-ro-follow-links` parameter, using the
-(non-ASF) http://github.com/isisaddons/isis-app-kitchensink[Isis addons' kitchensink] app as the example,
+This link:https://www.youtube.com/watch?v=hSKnqqBQ7Zo[screencast] demonstrates the Restful Object viewer's support for `x-ro-follow-links` parameter, using the (non-ASF) http://github.com/isisaddons/isis-app-kitchensink[Isis addons' kitchensink] app as the example,
 This app contains three entities, `Grandparent`, `Parent` and `Child` that define a hierarchy of 1:m relationships.
 
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionParameter.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionParameter.java
index df26433..a7cd6f4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionParameter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionParameter.java
@@ -113,7 +113,9 @@ public interface ObjectActionParameter extends ObjectFeature, CurrentHolder {
             final InteractionInitiatedBy interactionInitiatedBy);
 
 
-    ObjectAdapter getDefault(ObjectAdapter adapter);
+    ObjectAdapter getDefault(
+            ObjectAdapter adapter,
+            final ObjectAdapter[] argumentsIfAvailable);
 
     
     /**
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
index 57129a2..f9ccf82 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.core.metamodel.specloader.specimpl;
 
+import java.util.Arrays;
 import java.util.List;
 
 import com.google.common.collect.Lists;
@@ -373,10 +374,12 @@ public abstract class ObjectActionParameterAbstract implements ObjectActionParam
     //region > Defaults
 
     @Override
-    public ObjectAdapter getDefault(final ObjectAdapter adapter) {
+    public ObjectAdapter getDefault(
+            final ObjectAdapter adapter,
+            final ObjectAdapter[] argumentsIfAvailable) {
         
         final ObjectAdapter target = targetForDefaultOrChoices(adapter);
-        final List<ObjectAdapter> args = argsForDefaultOrChoices(adapter, null);
+        final List<ObjectAdapter> args = argsForDefaultOrChoices(adapter, argumentsIfAvailable != null ? Arrays.asList(argumentsIfAvailable) : null);
         
         return findDefault(target, args);
     }
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
index 436db7e..f9ef97a 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
@@ -194,7 +194,7 @@ public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<O
     }
 
     private Object defaultFor(final ObjectActionParameter param) {
-        final ObjectAdapter defaultAdapter = param.getDefault(objectAdapter);
+        final ObjectAdapter defaultAdapter = param.getDefault(objectAdapter, null);
         if (defaultAdapter == null) {
             return null;
         }
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
index 8ad74ca..26d07a4 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
@@ -183,6 +183,18 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
             }
 
             @Override
+            public ObjectAdapter getDefault(
+                    final ScalarModel scalarModel,
+                    final ObjectAdapter[] argsIfAvailable,
+                    final AuthenticationSession authenticationSession,
+                    final DeploymentCategory deploymentCategory) {
+                final PropertyMemento propertyMemento = scalarModel.getPropertyMemento();
+                final OneToOneAssociation property = propertyMemento.getProperty(scalarModel.getSpecificationLoader());
+                ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load(ConcurrencyChecking.NO_CHECK);
+                return property.getDefault(parentAdapter);
+            }
+
+            @Override
             public boolean hasChoices(final ScalarModel scalarModel) {
                 final PropertyMemento propertyMemento = scalarModel.getPropertyMemento();
                 final OneToOneAssociation property = propertyMemento.getProperty(scalarModel.getSpecificationLoader());
@@ -405,6 +417,19 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
             }
 
             @Override
+            public ObjectAdapter getDefault(
+                    final ScalarModel scalarModel,
+                    final ObjectAdapter[] argsIfAvailable,
+                    final AuthenticationSession authenticationSession,
+                    final DeploymentCategory deploymentCategory) {
+                final ActionParameterMemento parameterMemento = scalarModel.getParameterMemento();
+                final ObjectActionParameter actionParameter = parameterMemento.getActionParameter(scalarModel.getSpecificationLoader());
+
+                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
+                return actionParameter.getDefault(parentAdapter, argsIfAvailable);
+            }
+
+            @Override
             public boolean hasChoices(final ScalarModel scalarModel) {
                 final ActionParameterMemento parameterMemento = scalarModel.getParameterMemento();
                 final ObjectActionParameter actionParameter = parameterMemento.getActionParameter(scalarModel.getSpecificationLoader());
@@ -518,7 +543,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
                         scalarModel.getSpecificationLoader());
                 final ObjectAdapter parentAdapter =
                         scalarModel.getParentEntityModel().load(ConcurrencyChecking.NO_CHECK);
-                final ObjectAdapter defaultAdapter = actionParameter.getDefault(parentAdapter);
+                final ObjectAdapter defaultAdapter = actionParameter.getDefault(parentAdapter, null);
                 scalarModel.setObject(defaultAdapter);
             }
 
@@ -599,6 +624,12 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
             return required;
         }
 
+        public abstract ObjectAdapter getDefault(
+                final ScalarModel scalarModel,
+                final ObjectAdapter[] argsIfAvailable,
+                final AuthenticationSession authenticationSession,
+                final DeploymentCategory deploymentCategory);
+
         public abstract boolean hasChoices(ScalarModel scalarModel);
         public abstract List<ObjectAdapter> getChoices(
                 final ScalarModel scalarModel,
@@ -633,6 +664,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
         public abstract boolean isCollection(final ScalarModel scalarModel);
 
         public abstract String toStringOf(final ScalarModel scalarModel);
+
     }
 
     private final Kind kind;
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersForm.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersForm.java
index 9ad8edd..f55efcd 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersForm.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersForm.java
@@ -41,7 +41,6 @@ import org.apache.isis.viewer.wicket.model.mementos.ActionParameterMemento;
 import org.apache.isis.viewer.wicket.model.models.ActionArgumentModel;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
-import org.apache.isis.viewer.wicket.ui.components.scalars.PanelWithChoices;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract2;
 import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage;
 import org.apache.isis.viewer.wicket.ui.panels.FormExecutorStrategy;
@@ -144,27 +143,30 @@ class ActionParametersForm extends PromptFormAbstract<ActionModel> {
     }
 
     @Override
-    public void onUpdate(AjaxRequestTarget target, ScalarPanelAbstract2 scalarPanel) {
+    public void onUpdate(final AjaxRequestTarget target, final ScalarPanelAbstract2 currScalarPanel) {
 
         final ActionModel actionModel = getActionModel();
 
-        final ObjectAdapter[] pendingArguments = actionModel.getArgumentsAsArray();
-
         try {
             final ObjectAction action = actionModel.getActionMemento().getAction(getSpecificationLoader());
+
             final int numParams = action.getParameterCount();
-            for (int i = 0; i < numParams; i++) {
-                final ScalarPanelAbstract2 paramPanel = paramPanels.get(i);
-                if (paramPanel != null && paramPanel instanceof PanelWithChoices) {
-                    final PanelWithChoices panelWithChoices = (PanelWithChoices) paramPanel;
-
-                    // this could throw a ConcurrencyException as we may have to reload the
-                    // object adapter of the action in order to compute the choices
-                    // (and that object adapter might have changed)
-                    if (panelWithChoices.updateChoices(pendingArguments)) {
-                        paramPanel.repaint(target);
-                    }
+
+            // only updates subsequent parameter panels to this one.
+            boolean seenCurrent = false;
+            for (int paramNum = 0; paramNum < numParams; paramNum++) {
+                final ScalarPanelAbstract2 paramPanel = paramPanels.get(paramNum);
+                if(paramPanel == currScalarPanel) {
+                    seenCurrent = true;
+                    continue;
                 }
+                if(!seenCurrent) {
+                    continue;
+                }
+                if(paramPanel.updateIfNecessary(actionModel, paramNum)) {
+                    paramPanel.repaint(target);
+                }
+
             }
         } catch (ConcurrencyException ex) {
 
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/PanelWithChoices.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/PanelWithChoices.java
deleted file mode 100644
index 3b80a26..0000000
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/PanelWithChoices.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package org.apache.isis.viewer.wicket.ui.components.scalars;
-
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-
-public interface PanelWithChoices {
-
-    boolean updateChoices(ObjectAdapter[] argsIfAvailable);
-
-
-}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
index 47aefc1..3808eea 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
@@ -51,8 +51,14 @@ import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.labelat.LabelAtFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.mementos.ActionParameterMemento;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionArgumentModel;
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
 import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
@@ -106,6 +112,51 @@ public abstract class ScalarPanelAbstract2 extends PanelAbstract<ScalarModel> im
     private static final String ID_ASSOCIATED_ACTION_LINKS_BELOW = "associatedActionLinksBelow";
     private static final String ID_ASSOCIATED_ACTION_LINKS_RIGHT = "associatedActionLinksRight";
 
+    /**
+     * @param actionModel
+     * @param paramNum
+     * @return - true if changed as a result of these pending arguments.
+     */
+    public boolean updateIfNecessary(
+            final ActionModel actionModel,
+            final int paramNum) {
+
+        final ObjectAction action = actionModel.getActionMemento().getAction(getSpecificationLoader());
+        final ObjectAdapter[] pendingArguments = actionModel.getArgumentsAsArray();
+
+        final ScalarModel model = getModel();
+        ObjectAdapter defaultIfAny = model.getKind()
+                .getDefault(scalarModel, pendingArguments, getAuthenticationSession(), getDeploymentCategory());
+
+        final ObjectActionParameter actionParameter = action.getParameters().get(paramNum);
+        final ActionParameterMemento apm = new ActionParameterMemento(actionParameter);
+        final ActionArgumentModel actionArgumentModel = actionModel.getArgumentModel(apm);
+
+        final ObjectAdapter pendingArg = pendingArguments[paramNum];
+
+        if (defaultIfAny != null) {
+            scalarModel.setObject(defaultIfAny);
+            scalarModel.setPending(ObjectAdapterMemento.createOrNull(defaultIfAny));
+            actionArgumentModel.setObject(defaultIfAny);
+        } else {
+
+            if(pendingArg != null & scalarModel.hasChoices()) {
+                // make sure the object is one of the choices, else blank it out.
+                final List<ObjectAdapter> choices = scalarModel
+                            .getChoices(pendingArguments, getAuthenticationSession(), getDeploymentCategory());
+                if(!choices.contains(pendingArg)) {
+                    scalarModel.setObject(null);
+                    scalarModel.setPending(null);
+                    actionArgumentModel.setObject(null);
+                }
+            }
+        }
+
+        return scalarModel.getObject() != pendingArg;
+    }
+
+
+
     public static class InlinePromptConfig {
         private final boolean supported;
         private final Component componentToHideIfAny;
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelect2Abstract.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelect2Abstract.java
index d8bba2b..387f2da 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelect2Abstract.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelect2Abstract.java
@@ -41,6 +41,7 @@ import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
 import org.apache.isis.viewer.wicket.ui.components.widgets.select2.Select2;
@@ -166,16 +167,29 @@ public abstract class ScalarPanelSelect2Abstract extends ScalarPanelAbstract2 {
      * <p>
      * called from onUpdate callback
      */
-    public boolean updateChoices(ObjectAdapter[] argsIfAvailable) {
+    @Override
+    public boolean updateIfNecessary(
+            final ActionModel actionModel, final int paramNum) {
+
+        final boolean choicesUpdated = updateChoices(actionModel.getArgumentsAsArray());
+        final boolean currentUpdated =
+                super.updateIfNecessary(actionModel, paramNum);
+
+        return currentUpdated || choicesUpdated;
+    }
+
+    private boolean updateChoices(ObjectAdapter[] argsIfAvailable) {
         if (select2 == null) {
             return false;
         }
         setProviderAndCurrAndPending(select2, argsIfAvailable);
+
         return true;
     }
 
 
 
+
     /**
      * Repaints just the Select2 component
      *
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
index 295aeff..3b1688a 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
@@ -46,7 +46,6 @@ import org.apache.isis.viewer.wicket.model.models.EntityModelForReference;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.ui.ComponentFactory;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
-import org.apache.isis.viewer.wicket.ui.components.scalars.PanelWithChoices;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract2;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelSelect2Abstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
@@ -62,7 +61,7 @@ import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
  * Panel for rendering scalars which of are of reference type (as opposed to
  * value types).
  */
-public class ReferencePanel extends ScalarPanelSelect2Abstract implements PanelWithChoices {
+public class ReferencePanel extends ScalarPanelSelect2Abstract {
 
     private static final long serialVersionUID = 1L;
 
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/valuechoices/ValueChoicesSelect2Panel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/valuechoices/ValueChoicesSelect2Panel.java
index defe635..ec60511 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/valuechoices/ValueChoicesSelect2Panel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/valuechoices/ValueChoicesSelect2Panel.java
@@ -33,17 +33,15 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.viewer.wicket.model.isis.WicketViewerSettings;
 import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
-import org.apache.isis.viewer.wicket.ui.components.scalars.PanelWithChoices;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelSelect2Abstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.select2.Select2;
 import org.apache.isis.viewer.wicket.ui.components.widgets.select2.providers.ObjectAdapterMementoProviderForValueChoices;
 
-public class ValueChoicesSelect2Panel extends ScalarPanelSelect2Abstract implements PanelWithChoices {
+public class ValueChoicesSelect2Panel extends ScalarPanelSelect2Abstract {
 
 
     private static final long serialVersionUID = 1L;
 
-
     public ValueChoicesSelect2Panel(final String id, final ScalarModel scalarModel) {
         super(id, scalarModel);
     }