Index: src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItemGuiSupport.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItemGuiSupport.java	(revision 18079)
+++ src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItemGuiSupport.java	(working copy)
@@ -5,7 +5,6 @@
 import org.openstreetmap.josm.data.osm.Tag;
 import org.openstreetmap.josm.data.osm.Tagged;
 import org.openstreetmap.josm.data.osm.search.SearchCompiler;
-import org.openstreetmap.josm.gui.tagging.presets.items.KeyedItem;
 import org.openstreetmap.josm.tools.ListenerList;
 import org.openstreetmap.josm.tools.template_engine.TemplateEngineDataProvider;
 
@@ -13,7 +12,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.function.Supplier;
-import java.util.stream.Collectors;
 
 /**
  * Supporting class for creating the GUI for a preset item.
@@ -69,8 +67,9 @@
     /**
      * Creates a new {@code TaggingPresetItemGuiSupport}
      *
+     * @param presetInitiallyMatches whether the preset initially matched
      * @param selected the selected primitives
-     * @param presetInitiallyMatches whether the preset initially matched
+     * @param changedTagsSupplier the changed tags
      * @return the new {@code TaggingPresetItemGuiSupport}
      */
     public static TaggingPresetItemGuiSupport create(
@@ -81,8 +80,8 @@
     /**
      * Creates a new {@code TaggingPresetItemGuiSupport}
      *
+     * @param presetInitiallyMatches whether the preset initially matched
      * @param selected the selected primitives
-     * @param presetInitiallyMatches whether the preset initially matched
      * @return the new {@code TaggingPresetItemGuiSupport}
      */
     public static TaggingPresetItemGuiSupport create(
@@ -90,25 +89,38 @@
         return new TaggingPresetItemGuiSupport(presetInitiallyMatches, Arrays.asList(selected), Collections::emptyList);
     }
 
+    /**
+     * Get tags with values as currently shown in the dialog.
+     * If exactly one primitive is selected, get all tags of it, then 
+     * overwrite with the current values shown in the dialog.
+     * Else get only the tags shown in the dialog.
+     * @return Tags
+     */
+    public Tagged getTagged() {
+        if (selected.size() != 1) {
+            return Tagged.ofTags(changedTagsSupplier.get());
+        }
+        // if there is only one primitive selected, get its tags
+        Tagged tagged = Tagged.ofMap(selected.iterator().next().getKeys());
+        // update changed tags
+        changedTagsSupplier.get().forEach(tag -> tagged.put(tag));
+        return tagged;
+    }
+
     @Override
     public Collection<String> getTemplateKeys() {
-        return changedTagsSupplier.get().stream().map(Tag::getKey).collect(Collectors.toList());
+        return getTagged().keySet();
     }
 
     @Override
     public Object getTemplateValue(String key, boolean special) {
-        return changedTagsSupplier.get().stream()
-                .filter(tag -> key.equals(tag.getKey()))
-                .findFirst().map(Tag::getValue).orElseGet(() -> {
-                    KeyedItem.Usage usage = KeyedItem.determineTextUsage(getSelected(), key);
-                    return usage.hasUniqueValue() ? usage.getFirst() : null;
-                });
+        String value = getTagged().get(key);
+        return (value == null || value.isEmpty()) ? null : value;
     }
 
     @Override
     public boolean evaluateCondition(SearchCompiler.Match condition) {
-        Tagged tagged = Tagged.ofTags(changedTagsSupplier.get());
-        return condition.match(tagged);
+        return condition.match(getTagged());
     }
 
     /**
Index: src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java	(revision 18079)
+++ src/org/openstreetmap/josm/gui/tagging/presets/items/Text.java	(working copy)
@@ -238,6 +238,11 @@
         return Collections.singleton(default_);
     }
 
+    /**
+     * Set the value template.
+     * @param pattern The value_template pattern.
+     * @throws SAXException If an error occured while parsing.
+     */
     public void setValue_template(String pattern) throws SAXException { // NOPMD
         try {
             this.valueTemplate = new TemplateParser(pattern).parse();
@@ -248,16 +253,24 @@
     }
 
     private void setupListeners(AutoCompletingTextField textField, TaggingPresetItemGuiSupport support) {
-        if (valueTemplate == null) { // only fire on normal fields
+        // value_templates don't work well with multiple selected items because, 
+        // as the command queue is currently implemented, we can only save 
+        // the same value to all selected primitives, which is probably not 
+        // what you want.
+        if (valueTemplate == null || support.getSelected().size() > 1) { // only fire on normal fields
             textField.getDocument().addDocumentListener(DocumentAdapter.create(ignore ->
                     support.fireItemValueModified(this, key, textField.getText())));
         } else { // only listen on calculated fields
-            textField.setForeground(Color.BLUE);
             support.addListener((source, key, newValue) -> {
                 String valueTemplateText = valueTemplate.getText(support);
                 Logging.trace("Evaluating value_template {0} for key {1} from {2} with new value {3} => {4}",
                         valueTemplate, key, source, newValue, valueTemplateText);
                 textField.setItem(valueTemplateText);
+                if (originalValue != null && !originalValue.equals(valueTemplateText)) {
+                    textField.setForeground(Color.RED);
+                } else {
+                    textField.setForeground(Color.BLUE);
+                }
             });
         }
     }
