четверг, 28 августа 2014 г.

SharePoint 2013. ClientPeoplePicker & Custom forms

Многие уже знают, что в SharePoint 2013 появился новый замечательный элемент управления для работы с данными типа "Пользователь". Выглядит он так:
И именно этот элемент управления, с возможность предлагать возможные значения, отображается во всех формах элементов списка по умолчанию. И это очень хорошо.
Проблемы возникают когда Вы создаете новую форму.
Напомню, что в формах по умолчанию, за генерацию полей отвечает ListFormWebPart. Но если Вы создаете новую форму, то функцию генерации html полей на себя берет DataFormWebPart. При этом каждое отдельное поле генерируется элементом управления FormField. Кастомизировать форму становиться намного легче. Но при этом вместо нового ClientPeoplePicker мы видим старый контрол, без автокомплита и с кнопками проверки пользователя и кнопки для открытия всплывающего окна для поиска пользователя:
Как я уже упомянул, каждое поле генерируется SharePoint:FormField. Я пытался найти возможность "попросить" его вывести именно новый ClientPeoplePicker, но тщетно.
Мы сами можем добавить новый контрол на страницу, для этого добавим на форму такой код:


После этого у нас появится прекрасно работающий ClientPeoplePicker. Вот только нужно его привязать к полю и делать это нужно самому. Я сделал это спрятав основной контрол, который без автокомплита, но только спрятал, с самой формы не убирал. Дальше, используя JavaScript, в методе PreSaveAction() перед сохранением формы брал данные из ClientPeoplePicker и вставлял их в старый PeoplePicker. Что бы мне было удобно работать, я использовал библиотеку SPSservices.
// Заполняем поля в PeoplePicker
var arrUserField = [];
$("#UserFieldCPP_TopSpan span span span[class='ms-entity-resolved']").each(function(index, elem){
    arrUserField.push($(this).text());
});
var strUserField = arrUserField.join(";");

$().SPServices.SPFindPeoplePicker({
 peoplePickerDisplayName: "Сотрудник",
 valueToSet: strUserField ,
 checkNames: true
});
Т.е. перед сохранение формы данные из ClientPeoplePicker копируются в обычный PeoplePicker.
Приведенный код подходит для формы создания элемента, для формы редактирования нам нужно из обычного PeoplePicker'а скопировать в ClientPeoplePicker. Используйте этот код:

// Заполняем поля в ClientPeoplePicker
var UserFieldPP = $().SPServices.SPFindPeoplePicker({
 peoplePickerDisplayName: "Сотрудник" 
});

var UserFieldPPPeopleList = UserFieldPP.currentValue.split(";");
UserFieldPPPeopleList.pop(); 
var picker = SPClientPeoplePicker.SPClientPeoplePickerDict["UserFieldCPP_TopSpan"]

for (i = 0; i < UserFieldPPPeopleList.length; i++) { 
    var name = UserFieldPPPeopleList[i];
 $("#UserFieldCPP_TopSpan_EditorInput").val(name);
 picker.AddUnresolvedUserFromEditor(true)
}
Теперь кастомные формы могут иметь ClientPeoplePicker привязанный к полю в списке.
Код работает в т.ч. для множественных значений. Так же, что бы приведенный выше код работал, ID у ClientPeoplePicker должно быть "UserFieldCPP".