diff --git a/openbis/etc/web-client.properties b/openbis/etc/web-client.properties
index 01573c504665a4c680f10deb5c7f3dcfdf148ea6..d778963984a61c8a0979ade6daa26e6e3c0e0105 100644
--- a/openbis/etc/web-client.properties
+++ b/openbis/etc/web-client.properties
@@ -15,6 +15,10 @@ max-visible-columns = 25
 # If not specified image overview will not be shown for any datasets. 
 data-set-types-with-image-overview = HCS_IMAGE, UNKNOWN
 
+# (optional) Allows power users adding vocabulary terms when editing the form.
+# If not specified, default is false
+# allow-adding-unofficial-terms = true
+
 # Configuration of entity (experiment, sample, data set, material) detail views.
 #
 # Mandatory properties: 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java
index b3f83432057c1346c67e285934b5d822c5311c04..f948b9450f1c3a3cfd514c6e91e7eccf4b5bbf18 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/VocabularyTermSelectionWidget.java
@@ -57,14 +57,13 @@ public class VocabularyTermSelectionWidget extends
 
     private class UnofficialTermRegistrationDialog extends AbstractRegistrationDialog
     {
-        private final IViewContext<ICommonClientServiceAsync> viewContext;
+        private final IViewContext<?> viewContext;
 
         private final String code;
 
         private final Vocabulary vocabulary;
 
-        public UnofficialTermRegistrationDialog(
-                IViewContext<ICommonClientServiceAsync> viewContext, String code)
+        public UnofficialTermRegistrationDialog(IViewContext<?> viewContext, String code)
         {
             super(viewContext, viewContext
                     .getMessage(Dict.ADD_UNOFFICIAL_VOCABULARY_TERM_DIALOG_TITLE),
@@ -81,7 +80,7 @@ public class VocabularyTermSelectionWidget extends
         @Override
         protected void register(AsyncCallback<Void> registrationCallback)
         {
-            ICommonClientServiceAsync service = viewContext.getService();
+            ICommonClientServiceAsync service = viewContext.getCommonService();
 
             service.addUnofficialVocabularyTerms(TechId.create(vocabulary), Arrays.asList(code),
                     getMaxOrdinal(), registrationCallback);
@@ -106,6 +105,8 @@ public class VocabularyTermSelectionWidget extends
 
     private static final String CHOOSE_MSG = "Choose...";
 
+    private static final String CHOOSE_OR_ADD_MSG = "Choose or add new...";
+
     private static final String VALUE_NOT_IN_LIST_MSG = "Value not in the list";
 
     private static final String EMPTY_MSG = "- No terms found -";
@@ -116,7 +117,7 @@ public class VocabularyTermSelectionWidget extends
 
     private String initialTermCodeOrNull;
 
-    private String typedValue = null;
+    private String typedValueOrNull = null;
 
     /**
      * Allows to choose one of the specified vocabulary's terms, is able to refresh the available
@@ -143,8 +144,9 @@ public class VocabularyTermSelectionWidget extends
             Vocabulary vocabularyOrNull, final IViewContext<?> viewContextOrNull,
             List<VocabularyTerm> termsOrNull, String initialTermCodeOrNull)
     {
-        super(idSuffix, ModelDataPropertyNames.CODE_WITH_LABEL, label, CHOOSE_MSG, EMPTY_MSG,
-                VALUE_NOT_IN_LIST_MSG, mandatory, viewContextOrNull, termsOrNull == null);
+        super(idSuffix, ModelDataPropertyNames.CODE_WITH_LABEL, label,
+                allowAddingUnofficialTerms(viewContextOrNull) ? CHOOSE_OR_ADD_MSG : CHOOSE_MSG,
+                EMPTY_MSG, VALUE_NOT_IN_LIST_MSG, mandatory, viewContextOrNull, termsOrNull == null);
         this.viewContextOrNull = viewContextOrNull;
         this.vocabularyOrNull = vocabularyOrNull;
         this.initialTermCodeOrNull = initialTermCodeOrNull;
@@ -159,53 +161,58 @@ public class VocabularyTermSelectionWidget extends
         setTemplate(GWTUtils.getTooltipTemplate(VocabularyTermModel.DISPLAY_FIELD,
                 ModelDataPropertyNames.TOOLTIP));
 
-        if (viewContextOrNull != null
-                && viewContextOrNull.getModel().getApplicationInfo().getWebClientConfiguration()
-                        .getAllowAddingUnofficialTerms())
+        if (allowAddingUnofficialTerms(viewContextOrNull))
         {
-            this.addListener(Events.Blur, new Listener<BaseEvent>()
+            this.addListener(Events.Blur, createListenerAddingOnofficialTerms());
+        }
+    }
+
+    private static boolean allowAddingUnofficialTerms(IViewContext<?> viewContextOrNull)
+    {
+        return viewContextOrNull != null
+                && viewContextOrNull.getModel().getApplicationInfo().getWebClientConfiguration()
+                        .getAllowAddingUnofficialTerms();
+    }
+
+    private Listener<BaseEvent> createListenerAddingOnofficialTerms()
+    {
+        return new Listener<BaseEvent>()
+            {
+                public void handleEvent(BaseEvent be)
                 {
-                    public void handleEvent(BaseEvent be)
+                    if (VocabularyTermSelectionWidget.this.vocabularyOrNull != null
+                            && getSelection().size() != 1
+                            && (false == StringUtils.isBlank(VocabularyTermSelectionWidget.this
+                                    .getRawValue())))
                     {
-                        if (VocabularyTermSelectionWidget.this.vocabularyOrNull != null
-                                && VocabularyTermSelectionWidget.this.viewContextOrNull
-                                        .getService() instanceof ICommonClientServiceAsync
-                                && getSelection().size() != 1
-                                && (false == StringUtils.isBlank(VocabularyTermSelectionWidget.this
-                                        .getRawValue())))
+                        final String code = getRawValue().toUpperCase();
+                        if (!code.matches(CodeFieldKind.CODE_WITH_COLON.getPattern()))
                         {
-                            final String code = getRawValue().toUpperCase();
-                            if (!code.matches(CodeFieldKind.CODE_WITH_COLON.getPattern()))
-                            {
-                                Dialog d = new Dialog()
+                            Dialog d = new Dialog()
+                                {
+                                    @Override
+                                    protected void onButtonPressed(Button button)
                                     {
-                                        @Override
-                                        protected void onButtonPressed(Button button)
-                                        {
-                                            super.onButtonPressed(button);
-                                            VocabularyTermSelectionWidget.this.focus();
-                                        }
-                                    };
-                                d.setHeading(viewContextOrNull.getMessage(Dict.MESSAGEBOX_ERROR));
-                                d.addText(viewContextOrNull.getMessage(Dict.INVALID_CODE_MESSAGE,
-                                        CodeFieldKind.CODE_WITH_COLON.getAllowedCharacters()));
-                                d.setSize(400, 200);
-                                d.setHideOnButtonClick(true);
-                                d.setButtons(Dialog.OK);
-                                d.show();
-                            } else
-                            {
-                                @SuppressWarnings("unchecked")
-                                UnofficialTermRegistrationDialog d =
-                                        new UnofficialTermRegistrationDialog(
-                                                (IViewContext<ICommonClientServiceAsync>) viewContextOrNull,
-                                                code);
-                                d.show();
-                            }
+                                        super.onButtonPressed(button);
+                                        VocabularyTermSelectionWidget.this.focus();
+                                    }
+                                };
+                            d.setHeading(viewContextOrNull.getMessage(Dict.MESSAGEBOX_ERROR));
+                            d.addText(viewContextOrNull.getMessage(Dict.INVALID_CODE_MESSAGE,
+                                    CodeFieldKind.CODE_WITH_COLON.getAllowedCharacters()));
+                            d.setSize(400, 200);
+                            d.setHideOnButtonClick(true);
+                            d.setButtons(Dialog.OK);
+                            d.show();
+                        } else
+                        {
+                            UnofficialTermRegistrationDialog d =
+                                    new UnofficialTermRegistrationDialog(viewContextOrNull, code);
+                            d.show();
                         }
                     }
-                });
-        }
+                }
+            };
     }
 
     private IDelegatedAction createRefreshAction(final String _typedValue)
@@ -214,7 +221,7 @@ public class VocabularyTermSelectionWidget extends
             {
                 public void execute()
                 {
-                    VocabularyTermSelectionWidget.this.typedValue = _typedValue;
+                    VocabularyTermSelectionWidget.this.typedValueOrNull = _typedValue;
                     refreshStore();
                     clearInvalid();
                     focus();
@@ -261,15 +268,15 @@ public class VocabularyTermSelectionWidget extends
 
     public void selectInitialValue()
     {
-        if (typedValue != null)
+        if (typedValueOrNull != null)
         {
             try
             {
-                trySelectByCode(typedValue);
+                trySelectByCode(typedValueOrNull);
                 updateOriginalValue();
             } finally
             {
-                typedValue = null;
+                typedValueOrNull = null;
             }
         } else if (initialTermCodeOrNull != null)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index b941e1d66b95b103dbfefa8bb39cb746b604c51e..f1df931f9ea24ccadb18aecbef798eef703ce121 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -100,11 +100,11 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Project;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleAssignment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
-import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleUpdateResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleUpdateResult;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Script;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ScriptType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Space;
@@ -559,7 +559,7 @@ public interface ICommonServer extends IServer
      */
     @Transactional
     @RolesAllowed(RoleWithHierarchy.SPACE_POWER_USER)
-    @DatabaseCreateOrDeleteModification(value = ObjectKind.VOCABULARY_TERM)
+    @DatabaseUpdateModification(value = ObjectKind.VOCABULARY_TERM)
     public void makeVocabularyTermsOfficial(String sessionToken, TechId vocabularyId,
             List<VocabularyTerm> termsToBeOfficial);
 
@@ -837,7 +837,7 @@ public interface ICommonServer extends IServer
     public SampleParentWithDerived getSampleInfo(final String sessionToken,
             @AuthorizationGuard(guardClass = SampleTechIdPredicate.class) final TechId sampleId)
             throws UserFailureException;
-    
+
     /**
      * Saves changed sample.
      */