diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst
index b180820350a839374218e2ffcf098c48486678f8..d5166fb7317243142eb652792ba997bdf532ec7f 100644
--- a/extension/Documentation/Manual.rst
+++ b/extension/Documentation/Manual.rst
@@ -862,31 +862,46 @@ parameter
 
   * Comments: lines starting with a '#' are treated as a comment and will not be parsed.
 
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| Name                   | Type   | Description                                                                                              |
-+========================+========+==========================================================================================================+
-| maxVisiblePill         | int    | Show pills upto <maxVisiblePill> as button, all further in a dropdown menu. Eg.: maxVisiblePill=3        |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| class                  | string | HTML div with given class, surrounding the whole form. Eg.: class=container-fluid                        |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| classPill              | string | HTML div with given class, surrounding the `pill` title line.                                            |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| classBody              | string | HTML div with given class, surrounding all *FormElement*.                                                |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| submitButtonText       | string | Show save button, with the <submitButtonText> at the bottom of the form                                  |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| extraDeleteForm        | string | Name of a form which specifies how to delete the primary record and optional slave records               |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| data-pattern-error     | string | Pattern violation: Text for error message used for all FormElements of current form                      |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| data-required-error    | string | Required violation: Text for error message used for all FormElements of current form                     |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| data-match-error       | string | Match violation: Text for error message used for all FormElements of current form                        |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| data-error             | string | If none specific is defined: Text for error message used for all FormElements of current form            |
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| buttonOnChangeClass    | string | Color for save button after user modified some content or current form. E.g.: 'btn-info alert-info'      +
-+------------------------+--------+----------------------------------------------------------------------------------------------------------+
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| Name                     | Type   | Description                                                                                              |
++==========================+========+==========================================================================================================+
+| maxVisiblePill           | int    | Show pills upto <maxVisiblePill> as button, all further in a dropdown menu. Eg.: maxVisiblePill=3        |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| class                    | string | HTML div with given class, surrounding the whole form. Eg.: class=container-fluid                        |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| classPill                | string | HTML div with given class, surrounding the `pill` title line.                                            |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| classBody                | string | HTML div with given class, surrounding all *FormElement*.                                                |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| submitButtonText         | string | Show save button, with the <submitButtonText> at the bottom of the form                                  |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| extraDeleteForm          | string | Name of a form which specifies how to delete the primary record and optional slave records               |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| data-pattern-error       | string | Pattern violation: Text for error message used for all FormElements of current form                      |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| data-required-error      | string | Required violation: Text for error message used for all FormElements of current form                     |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| data-match-error         | string | Match violation: Text for error message used for all FormElements of current form                        |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| data-error               | string | If none specific is defined: Text for error message used for all FormElements of current form            |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| buttonOnChangeClass      | string | Color for save button after user modified some content or current form. E.g.: 'btn-info alert-info'      +
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| ldapServer               | string | FQDN Ldap Server. E.g.: ldap.example.com                                                                 |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| ldapBaseDn               | string | E.g.: ou=dept,dc=example,dc=com                                                                          |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| ldapSearch               | string | E.g.: (|(cn=*?*)(mail=*?*)(ou=*?*)(roomNumber=*?*)(telephoneNumber=*?*))                                 |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| typeAheadLimit           | int    | Maximum number of entries. The limit is applied to the server (LDAP or SQL) and the Client               |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| typeAheadMinLength       | int    | Minimum number of characters which have to typed to start the search.                                    |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| typeAheadLdapValuePrintf | string | Value formatting of LDAP result, per entry. E.g.: '%s / %s / %s', mail, roomnumber, telephonenumber      |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| typeAheadLdapKeyPrintf   | string | Key formatting of LDAP result, per entry. E.g.: '%s', mail                                               |
++--------------------------+--------+----------------------------------------------------------------------------------------------------------+
+
 
 * Example:
 
@@ -1398,9 +1413,9 @@ Type Ahead
 ''''''''''
 
 Activating `typeahead` functionality offers an instant lookup of data and displaying them to the user, while the user is
-typing. A dropdown box offers the results. As datasource the regular SQL connection or a LDAP query can be used.
+typing a dropdown box offers the results. As datasource the regular SQL connection or a LDAP query can be used.
 With every keystroke (starting from the *typeAheadMinLength* characters), the already typed value will be transmitted to
-the server, the lookup will be performed and the result is displayed as the dropdown box.
+the server, the lookup will be performed and the result, upto *typeAheadLimit* entries, are displayed as the dropdown box.
 
 * *FormElement.parameter*:
 
@@ -1410,6 +1425,11 @@ the server, the lookup will be performed and the result is displayed as the drop
 Depending of the `typeahead` setup, the given FormElement will contain the displayed `value` or `key` (if a key/value dict is
 configured).
 
+Configuration via Form / FormElement
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+All of the `typeAhead*` (exception: `typeAheadLdap`) and `ldap*` parameter can be specified in either on the Form.parameter or on FormElement.parameter.
+
 SQL
 ;;;
 
@@ -1427,9 +1447,11 @@ LDAP
 
 * *FormElement.parameter*:
 
-  * *typeAheadLdapServer* = FQDN of the searched server. E.g.: `directory.uzh.ch`
-  * *typeAheadLdapBaseDn* = Base DN. E.g.: `ou=Addressbook,dc=uzh,dc=ch`
-  * *typeAheadLdapSearch* = LDAP search expression. E.g.: `(|(cn=*?*)(mail=*?*)(ou=*?*)(roomNumber=*?*)(telephoneNumber=*?*))`
+  * *typeAheadLdap*  This entry activates the *LDAP* typeahead functionality.
+  * *ldapServer* = FQDN of the searched server. E.g.: `directory.uzh.ch`
+  * *ldapBaseDn* = Base DN. E.g.: `ou=Addressbook,dc=uzh,dc=ch`
+  * *ldapSearch* = LDAP search expression. Every '?' will be replaced with the current typed content.
+     E.g.: `(|(cn=*?*)(mail=*?*)(ou=*?*)(roomNumber=*?*)(telephoneNumber=*?*))`
   * *typeAheadLdapValuePrintf* = regular printf expression, LDAP attributenames will be used as variablenames. Will be shown
       in the dropdownbox. E.g.: `'%s / %s / %s', mail, roomNumber, telephoneNumber`
   * *typeAheadLdapKeyPrintf* = Same as `ldapValuePrintf` - on save, these content will be saved. E.g.: `'%s', mail`
diff --git a/extension/qfq/api/typeahead.php b/extension/qfq/api/typeahead.php
index e635c8ec782044f6b870db0d5ac54243064fe2a9..cfd2e44e1d19dec4578e3303ebb4a7f997e06911 100644
--- a/extension/qfq/api/typeahead.php
+++ b/extension/qfq/api/typeahead.php
@@ -19,15 +19,14 @@ require_once(__DIR__ . '/../qfq/Constants.php');
  * Return JSON encoded answer
  *
  */
-
-
 try {
     $qfq = new \qfq\TypeAhead();
 
     $answer = $qfq->process();
 
 } catch (\Exception $e) {
-    $answer[API_MESSAGE] = "Generic Exception: " . $e->getMessage();
+//    $answer[API_MESSAGE] = "Generic Exception: " . $e->getMessage();
+    $answer[] = [API_TYPEAHEAD_KEY => 'errror', API_TYPEAHEAD_VALUE => "Error: " . $e->getMessage()];
 }
 
 header("Content-Type: application/json");
diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php
index a3c72f4a923f7fa4d7fc0079fcb77b5bb4bd1d0a..f910a51b6d9166fb75aad860f0bc6253eac6e4e6 100644
--- a/extension/qfq/qfq/AbstractBuildForm.php
+++ b/extension/qfq/qfq/AbstractBuildForm.php
@@ -382,6 +382,10 @@ abstract class AbstractBuildForm {
             // Preparation for Log, Debug
             $this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($fe), STORE_SYSTEM);
 
+            if (isset($fe[FE_FILL_STORE_LDAP]) || isset($fe[FE_TYPEAHEAD_LDAP])) {
+                $fe = $this->prepareLdapConfig($fe);
+            }
+
             // for Upload FormElements, it's necessary to precalculate an optional given 'slaveId'.
             if ($fe[FE_TYPE] === FE_TYPE_UPLOAD) {
                 Support::setIfNotSet($fe, FE_SLAVE_ID);
@@ -461,6 +465,24 @@ abstract class AbstractBuildForm {
         return $html;
     }
 
+    /**
+     * Copy LDAP Server from $this->formSpec to $formElement if they are not specified on $formElement
+     * @param array $formElement
+     * @return array
+     */
+    private function prepareLdapConfig(array $formElement) {
+
+        foreach ([F_LDAP_SERVER, F_LDAP_BASE_DN, F_LDAP_SEARCH, F_TYPEAHEAD_LIMIT,
+                     F_TYPEAHEAD_MINLENGTH, F_TYPEAHEAD_LDAP_VALUE_PRINTF, F_TYPEAHEAD_LDAP_KEY_PRINTF] as $key) {
+            if (!isset($formElement[$key])) {
+                if (isset($this->formSpec[$key])) {
+                    $formElement[$key] = $this->formSpec[$key];
+                }
+            }
+        }
+
+        return $formElement;
+    }
     /**
      * Check if there is an explicit 'autofocus' definition in at least one FE.
      * Found: do nothing, it will be rendered at the correct position.
@@ -824,17 +846,17 @@ abstract class AbstractBuildForm {
         if (isset($formElement[FE_TYPEAHEAD_SQL])) {
             $sql = $this->checkSqlAppendLimit($formElement[FE_TYPEAHEAD_SQL], $formElement[FE_TYPEAHEAD_LIMIT]);
             $urlParam = FE_TYPEAHEAD_SQL . '=' . $sql;
-        } elseif (isset($formElement[FE_TYPEAHEAD_LDAP_SERVER])) {
-            $formElement[FE_TYPEAHEAD_LDAP_SERVER] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_SERVER);
-            $formElement[FE_TYPEAHEAD_LDAP_BASE_DN] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_BASE_DN);
-            $formElement[FE_TYPEAHEAD_LDAP_SEARCH] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_SEARCH);
+        } elseif (isset($formElement[FE_LDAP_SERVER])) {
+            $formElement[FE_LDAP_SERVER] = Support::setIfNotSet($formElement, FE_LDAP_SERVER);
+            $formElement[FE_LDAP_BASE_DN] = Support::setIfNotSet($formElement, FE_LDAP_BASE_DN);
+            $formElement[FE_LDAP_SEARCH] = Support::setIfNotSet($formElement, FE_LDAP_SEARCH);
             $formElement[FE_TYPEAHEAD_LDAP_VALUE_PRINTF] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_VALUE_PRINTF);
             $formElement[FE_TYPEAHEAD_LDAP_KEY_PRINTF] = Support::setIfNotSet($formElement, FE_TYPEAHEAD_LDAP_KEY_PRINTF);
 
             $arr = [
-                FE_TYPEAHEAD_LDAP_SERVER => $formElement[FE_TYPEAHEAD_LDAP_SERVER],
-                FE_TYPEAHEAD_LDAP_BASE_DN => $formElement[FE_TYPEAHEAD_LDAP_BASE_DN],
-                FE_TYPEAHEAD_LDAP_SEARCH => $formElement[FE_TYPEAHEAD_LDAP_SEARCH],
+                FE_LDAP_SERVER => $formElement[FE_LDAP_SERVER],
+                FE_LDAP_BASE_DN => $formElement[FE_LDAP_BASE_DN],
+                FE_LDAP_SEARCH => $formElement[FE_LDAP_SEARCH],
                 FE_TYPEAHEAD_LDAP_VALUE_PRINTF => $formElement[FE_TYPEAHEAD_LDAP_VALUE_PRINTF],
                 FE_TYPEAHEAD_LDAP_KEY_PRINTF => $formElement[FE_TYPEAHEAD_LDAP_KEY_PRINTF],
                 FE_TYPEAHEAD_LIMIT => $formElement[FE_TYPEAHEAD_LIMIT],
diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php
index 80d4f02c0963216443b2cde258248433d3c64f43..072b225be64afbfa7b2e2a88e1dfe444fa95857c 100644
--- a/extension/qfq/qfq/Constants.php
+++ b/extension/qfq/qfq/Constants.php
@@ -531,6 +531,13 @@ const F_FE_DATA_ERROR = 'data-error';
 
 const F_PARAMETER = 'parameter';    // valid for F_ and FE_
 
+const F_LDAP_SERVER = 'ldapServer';
+const F_LDAP_BASE_DN = 'ldapBaseDn';
+const F_LDAP_SEARCH = 'ldapSearch';
+const F_TYPEAHEAD_LIMIT = 'typeAheadLimit';
+const F_TYPEAHEAD_MINLENGTH = 'typeAheadMinLength';
+const F_TYPEAHEAD_LDAP_VALUE_PRINTF = 'typeAheadLdapValuePrintf';
+const F_TYPEAHEAD_LDAP_KEY_PRINTF = 'typeAheadLdapKeyPrintf';
 
 // FORM_ELEMENT_STATI
 const FE_MODE_SHOW = 'show';
@@ -611,14 +618,16 @@ const FE_TEMPLATE_GROUP_CLASS = 'tgClass';
 const FE_TEMPLATE_GROUP_DEFAULT_MAX_LENGTH = 5;
 const FE_TEMPLATE_GROUP_NAME_PATTERN = '%d';
 const FE_BUTTON_CLASS = 'buttonClass';
-const FE_TYPEAHEAD_LIMIT = 'typeaheadLimit';
-const FE_TYPEAHEAD_MINLENGTH = 'typeaheadMinLength';
+const FE_LDAP_SERVER = F_LDAP_SERVER;
+const FE_LDAP_BASE_DN = F_LDAP_BASE_DN;
+const FE_LDAP_SEARCH = F_LDAP_SEARCH;
+const FE_TYPEAHEAD_LIMIT = F_TYPEAHEAD_LIMIT;
+const FE_TYPEAHEAD_MINLENGTH = F_TYPEAHEAD_MINLENGTH;
 const FE_TYPEAHEAD_SQL = 'typeAheadSql';
-const FE_TYPEAHEAD_LDAP_SERVER = 'typeAheadLdapServer';
-const FE_TYPEAHEAD_LDAP_BASE_DN = 'typeAheadLdapBaseDn';
-const FE_TYPEAHEAD_LDAP_SEARCH = 'typeAheadLdapSearch';
-const FE_TYPEAHEAD_LDAP_VALUE_PRINTF = 'typeAheadLdapValuePrintf';
-const FE_TYPEAHEAD_LDAP_KEY_PRINTF = 'typeAheadLdapKeyPrintf';
+const FE_TYPEAHEAD_LDAP_VALUE_PRINTF = F_TYPEAHEAD_LDAP_VALUE_PRINTF;
+const FE_TYPEAHEAD_LDAP_KEY_PRINTF = F_TYPEAHEAD_LDAP_KEY_PRINTF;
+const FE_TYPEAHEAD_LDAP = 'typeAheadLdap';
+const FE_FILL_STORE_LDAP = 'fillStoreLdap';
 const FE_CHARACTER_COUNT_WRAP = 'characterCountWrap';
 const RETYPE_FE_NAME_EXTENSION = 'RETYPE';
 
diff --git a/extension/qfq/qfq/form/TypeAhead.php b/extension/qfq/qfq/form/TypeAhead.php
index 87545b6cab77607f3235ae870973ea98bae844bd..fbfc280bc7da6a93d0815dcd131b67c73389b7c4 100644
--- a/extension/qfq/qfq/form/TypeAhead.php
+++ b/extension/qfq/qfq/form/TypeAhead.php
@@ -80,7 +80,7 @@ class TypeAhead {
 
         if (isset($sipVars[FE_TYPEAHEAD_SQL])) {
             $arr = $this->typeAheadSql($sipVars, $this->vars[TYPEAHEAD_API_QUERY]);
-        } elseif (isset($sipVars[FE_TYPEAHEAD_LDAP_SERVER])) {
+        } elseif (isset($sipVars[FE_LDAP_SERVER])) {
             $ldap = new Ldap();
             $arr = $ldap->process($sipVars, $this->vars[TYPEAHEAD_API_QUERY]);
         }
diff --git a/extension/qfq/qfq/helper/Ldap.php b/extension/qfq/qfq/helper/Ldap.php
index ced53b734c2b9110dcce909fe083281469c01a2c..f69f38a69efe95f1a57a772245ad00ce62df211e 100644
--- a/extension/qfq/qfq/helper/Ldap.php
+++ b/extension/qfq/qfq/helper/Ldap.php
@@ -23,9 +23,9 @@ class Ldap {
     public function process($config, $query) {
         $arr = array();
 
-        $ldapServer = $config[FE_TYPEAHEAD_LDAP_SERVER];
-        $ldapBaseDn = $config[FE_TYPEAHEAD_LDAP_BASE_DN];
-        $ldapSearch = $config[FE_TYPEAHEAD_LDAP_SEARCH];
+        $ldapServer = $config[FE_LDAP_SERVER];
+        $ldapBaseDn = $config[FE_LDAP_BASE_DN];
+        $ldapSearch = $config[FE_LDAP_SEARCH];
         $ldapSearch = str_replace('?', $query, $ldapSearch);
         $ldapLimit = $config[FE_TYPEAHEAD_LIMIT];
 
@@ -34,6 +34,18 @@ class Ldap {
             throw new UserFormException("Unable to connect to LDAP server: $ldapServer", ERROR_LDAP_CONNECT);
         }
 
+        if ($config[FE_TYPEAHEAD_LDAP_KEY_PRINTF] == '') {
+            $config[FE_TYPEAHEAD_LDAP_KEY_PRINTF] = $config[FE_TYPEAHEAD_LDAP_VALUE_PRINTF];
+        }
+
+        if ($config[FE_TYPEAHEAD_LDAP_VALUE_PRINTF] == '') {
+            $config[FE_TYPEAHEAD_LDAP_VALUE_PRINTF] = $config[FE_TYPEAHEAD_LDAP_KEY_PRINTF];
+        }
+
+        if ($config[FE_TYPEAHEAD_LDAP_KEY_PRINTF] == '') {
+            throw new UserFormException("Missing parameter '" . FE_TYPEAHEAD_LDAP_KEY_PRINTF . "' and/or '" . FE_TYPEAHEAD_LDAP_VALUE_PRINTF);
+        }
+
         $keyArr = $this->printfPrepare($config[FE_TYPEAHEAD_LDAP_KEY_PRINTF], $keyFormat);
         $valueArr = $this->printfPrepare($config[FE_TYPEAHEAD_LDAP_VALUE_PRINTF], $valueFormat);
 
@@ -69,9 +81,9 @@ class Ldap {
     /**
      * Very specific function to prepare the later 'printfResult()'.
      *
-     * @param $fmtComplete
-     * @param $fmtFirst
-     * @return mixed
+     * @param $fmtComplete  printf format string with all args.
+     * @param $fmtFirst     returns the first part of $fmtComplete - the printf format string without any args.
+     * @return array        Array with all requested keynames from $fmtComplete
      * @throws CodeException
      * @throws UserFormException
      */