Personenfelder vorbelegen

Eine oft gestellte Frage zu SharePoint ist die, wie man ein Personenfeld mit dem aktuellen Benutzer vorbelegen kann und genau das soll in diesem Beitrag gezeigt werden.

Es gibt grundsätzlich zwei Möglichkeiten: die erste besteht darin, das Feld erst nach der eigentlichen Neuanlage zu setzen. Das kann dann z.B. per EventReceiver oder per Workflow geschehen. Die zweite Möglichkeit besteht darin, das Eingabefeld auf dem Formular zur Neuanlage (NewForm.aspx) per JavaScript vorzubelegen und genau das wird hier gezeigt.

Update: hier ein ergänzender Beitrag, der zeigt wie man dasselbe deutlich einfacher mit jQuery erreichen kann. 

Wir brauchen also zunächst eine Möglichkeit das Formular mit JavaScript zu erweitern. Auch hierzu gibt es wieder zwei Möglichkeiten: die erste ist NewForm.aspx in SharePoint Designer zu öffnen und den Code direkt in die Seite einzufügen. Die zweite Möglichkeit ist das Formular im Browser zu bearbeiten, ein Inhaltseditor-Webpart einzufügen und dort den Code zu platzieren. Ich werde hier die Vorgehensweise mit SharePoint Designer beschreiben. Im Browser muß nur der fertige JavaScript-Code vom Ende des Beitrags in die HTML-Ansicht eines Inhaltseditor-Webparts kopiert werden.

Man öffnet also die Website in SharePoint Designer, klickt dann links auf Listen und Bibliotheken, dann auf die gewünschte Liste und schließlich rechts unter Formulare auf NewForm.aspx. Anschließend muß über das Menüband noch der erweiterte Modus aktiviert werden. In der Codeansicht sucht man sich jetzt eine geeignete Stelle zum Einfügen des Scripts. Geeignet sind z.B. die Platzhalter PlaceHolderAdditionalPageHead und PlaceHolderMain.

Zur Ermittlung des aktuellen Benutzers bedienen wir uns des Client Object Model für ECMAScript. Man könnte damit auch anderen Code ausführen, um einen bestimmten Benutzer zu ermitteln, aber für das Beispiel beschränke ich mich auf den aktuell angemeldeten Benutzer. Wenn man immer nur einen ganz bestimmten Benutzer vorbelegen möchte, kann man auch ganz darauf verzichten und diesen fest einprogrammieren.

Den aktuellen Benutzer bekommt man so:

var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var currentUser = web.get_currentUser();
ctx.load(currentUser);

Wie immer, wenn man das Client Object Model verwendet, muß anschließend ein executeQueryAsync ausgeführt werden, damit die gewünschten Daten auch wirklich geladen werden:

ctx.executeQueryAsync(function () {
   
// hier stehen die Daten zur Verfügung
  }, function (sender, args) {
    alert("Fehler: " + args.get_message());
  }
);

Die erste angegebene Funktion wird im Erfolgsfall und die zweite im Fehlerfall aufgerufen. Zum Testen kann man sich wie hier gezeigt eine Fehlermeldung ausgeben lassen. Bei einem Produktivsystem kann man die Funktion aber auch leer lassen und Fehler damit einfach "verschlucken".

Machen wir also an der Stelle weiter, die ausgeführt wird, wenn der Benutzer erfolgreich geladen wurde. Wir brauchen jetzt Zugriff auf das HTML-Element, das bei einem Personenfeld für die Eingabe vorhanden ist. Leider ist das bei Personenfeldern nicht ganz so einfach, wie bei anderen Feldtypen. Und es gibt nicht nur das altbekannte Eingabefeld (ein <div>), sondern auch ein standardmäßig ausgeblendetes <textarea>, das für ältere Browser erzeugt wird.

Da man Personenfelder im HTML nicht einfach über den Feldnamen identifizieren kann, erstellen wir eine wiederverwendbare Funktion, die alle Personenfelder durchgeht und das mit dem gewünschten Index zurückgibt. Wenn es mehrere Personenfelder gibt, können wir diese Funktion also mehrmals aufrufen und so z.B. das erste und das dritte Personenfeld vorbelegen:

function getPickerDiv(pickerNo) {
 
var divs = document.getElementsByTagName("DIV"),
      length = divs.length,
      i,
      j = 0;

  for
(i = 0; i < length; i++) {
    if (divs[i].id.indexOf("UserField_upLevelDiv") > 0) {
      if (j == pickerNo) {
        return divs[i];
      }
      j++;
    }
  }
  return null;
}

Diese Funktion liefert uns die <div>s für die Standardeingabemethode. Wir erstellen gleich noch eine zweite Funktion, die uns die <textarea>s liefert, damit wird die ebenfalls vorbelegen können:

function getPickerTextarea(pickerNo) {
 
var tas = document.getElementsByTagName("TEXTAREA"),
      length = tas.length,
      i,
      j = 0;

  for
(i = 0; i < length; i++) {
    if (tas[i].id.indexOf("UserField_downlevelTextBox") > 0) {
      if (j == pickerNo) {
        return tas[i];
      }
      j++;
    }
  }
  return null;
}

Jetzt brauchen wir diese Funktionen nur noch in den Code von oben einbauen und können dann den Benutzernamen z.B. in das erste Personenfeld einfügen:

var ele = getPickerDiv(0);
if (ele != null) {
  ele.innerHTML = currentUser.get_title();
}
ele = getPickerTextarea(0);
if (ele != null) {
  ele.value = currentUser.get_title();
}

Bitte beachten, daß beim <div> die innerHTML-Eigenschaft und beim <textarea> die value-Eigenschaft gesetzt wird.

Den Code packen wir jetzt noch in eine weitere Funktion setPicker, die dann beim Laden der Seite aufgerufen werden muß. Um dabei sicherzustellen, daß das Client Object Model zur Verfügung steht, verwenden wir die vordefinierte ExecuteOrDelayUntilScriptLoaded-Methode:

ExecuteOrDelayUntilScriptLoaded(setPicker, "sp.js");

Hier nochmal der gesamte JavaScript-Code zum bequemen Kopieren&Einfügen:

<script type="text/javascript">
ExecuteOrDelayUntilScriptLoaded(setPicker, "sp.js");
function setPicker() {
  var ctx = SP.ClientContext.get_current(),
      web = ctx.get_web(),
      currentUser = web.get_currentUser(),
      pickerNo = 0;

  ctx.load(currentUser);
  ctx.executeQueryAsync(function () {
      var ele = getPickerDiv(pickerNo);
      if (ele != null) {
        ele.innerHTML = currentUser.get_title();
      }
      ele = getPickerTextarea(pickerNo);
      if (ele != null) {
        ele.value = currentUser.get_title();
      }
    }, function (sender, args) {
      alert("Fehler: " + args.get_message());
    }
  );
}
function getPickerDiv(pickerNo) {
  var divs = document.getElementsByTagName("DIV"),
      length = divs.length,
      i,
      j = 0;

  for
(i = 0; i < length; i++) {
    if (divs[i].id.indexOf("UserField_upLevelDiv") > 0) {
      if (j == pickerNo) {
        return divs[i];
      }
      j++;
    }
  }
  return null;
}
function getPickerTextarea(pickerNo) {
  var tas = document.getElementsByTagName("TEXTAREA"),
      length = tas.length,
      i,
      j = 0;

  for
(i = 0; i < length; i++) {
    if (tas[i].id.indexOf("UserField_downlevelTextBox") > 0) {
      if (j == pickerNo) {
        return tas[i];
      }
      j++;
    }
  }
  return null;
}
</script>

3 Gedanken zu “Personenfelder vorbelegen

  1. Hallo Klaus,

    tut mir sehr leid für die späte Reaktion, aber der Server hat irgendwie vergessen, mich über Deinen Kommentar zu benachrichtigen 😦

    Natürlich kannst Du auch einzelne User ausschließen. Du mußt nur definieren, welche das sind und was genau die nicht dürfen. Über das currentUser-Objekt kannst Du die ID, den Login, die EMail und anderes testen und dann entsprechend reagieren.

    Viele Grüße
    Andi

Hinterlasse einen Kommentar