Sunday 17 July 2016

Отношения мастер-деталь в SharePoint 2013 между списками

Как построить связи между списками SharePoint в рамках отношений Один ко Многим, Много ко Многим и организовать между ними нечто подобие ссылочной целостности?
Наверняка этот вопрос задавали себе многие начинающие программисты SharePoin, так как стандартные средства этой великолепной системы управления сайтами не позволяют организовать полноценную ссылочную целостность между списками.

На самом деле построить каскадные отношения между списками несложно. Давайте рассмотрим небольшой пример на эту тему:

1. Создадим список сотрудников:
<?xml version="1.0" encoding="utf-8"?>
<List xmlns:ows="Microsoft SharePoint" Title="MFCEmployees" Name="MFCEmployees"
 Direction="$Resources:Direction;" Url="Lists/MFCEmployees" BaseType="0" 
xmlns="http://schemas.microsoft.com/sharepoint/" EnableContentTypes="TRUE">
  <MetaData>
       <ContentTypes>         
    <ContentType JSLink="~site/_layouts/15/webservice_001/
MyContent001/JS/MFCEmployees/MFCEmployees.js" 
ID="0x01005174e8c58336491db85ea917c7f65031" Name="Полное представление">
       <FieldRefs>                               
       <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" />
       <FieldRef ID="{ca828b4b-d9cf-4653-b4a5-2d44d3e9b9df}" Name="EmployeeName" />
       <FieldRef ID="{66cf8cfe-39b9-4123-bdaf-c36b7774dcd9}" Name="Birthdate" />
       <FieldRef ID="{254aabea-f690-4a88-b258-4fe87c61c612}" Name="Date_MFC_Employment" />
       <FieldRef ID="{163c8a49-88be-46e4-837c-57f3e0c1d96c}" Name="EmployeeStatus" />
       <FieldRef ID="{6d47a98d-c144-44ba-9912-339119c25681}" Name="Situation" />
       <FieldRef ID="{0655a999-cdc3-4c35-8b53-3bbd49e8192d}" Name="StatusEmployee" />
       <FieldRef ID="{6345b705-0bce-4e42-8b3e-0b3e3d37fe94}" Name="EndDateWork" />
       <FieldRef ID="{b5544a5a-5950-485e-8b3f-4286adbecb78}" Name="CompensatoryLeave" />
       <FieldRef ID="{234309e1-1823-4ad4-aba6-3c6390a378c6}" Name="Otdel" />
    </FieldRefs>
    </ContentType><ContentTypeRef ID="0x0120" /></ContentTypes>

    ФАЙЛ Schema.xml СОКРАЩЕН

  </MetaData>
</List>
Теперь создадим подчиненный список статусов сотрудников:
<?xml version="1.0" encoding="utf-8"?>
<List Id="{ca222b4b-d9cf-4653-b4a5-2d44d3e9b9df}" xmlns:ows="Microsoft SharePoint" 
Title="MFCEmployeesStatus" FolderCreation="FALSE" Direction="$Resources:Direction;"
 Url="Lists/MFCEmployeesStatus" BaseType="0" 
xmlns="http://schemas.microsoft.com/sharepoint/" EnableContentTypes="TRUE">
  <MetaData>
    <ContentTypes>        
      <ContentType ID="0x01005fec9402a88147e6937d2c0a3fb6303b" 
Name="Даты текущего состояния">
        <FieldRefs>                   
        <FieldRef ID="{4f243fe7-3f34-4e48-9c29-49f538bd4885}" Name="StatusEmployee" />
<FieldRef ID="{41790c3c-762d-4f2d-b570-939ab8281679}" Name="StartDateWork" />
<FieldRef ID="{e5da87f0-b02b-47f1-88d9-ce2cfc511ff1}" Name="EndDateWork" />
<FieldRef ID="{a50cd5f7-67ab-40d6-b9be-3ffcc6ff54e7}" Name="MFCEmployeesId" />
</FieldRefs>
      </ContentType><ContentTypeRef ID="0x01" /><ContentTypeRef ID="0x0120" />
</ContentTypes>

ФАЙЛ Schema.xml СОКРАЩЕН

  </MetaData>
</List>

Обратите внимание - у списка MFCEmployeesStatus объявлен столбец MFCEmployeesId. Это вторичный ключ списка MFCEmployees. По нему мы и будем строить отношения между списками по принципу Один ко Многим, где мастер - MFCEmployees, а деталь - MFCEmployeesStatus.

Теперь. когда у нас готовы списки нам необходимо создать механизм связывания двух списков по вторичному ключу. Для этого мы воспользуемся API SharePoint REST.
Без долгих объяснений прилагаю код соответствующих функций:
1. MFCEmployeesId.js:
SP.SOD.executeFunc("clienttemplates.js""SPClientTemplates"function () {
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
        Templates: {
            Fields: {
                //имя поля
                'MFCEmployeesId':
                {
                    NewForm: function (ctx) {
                        var qur = GetUrlKeyValue('MFCEmployeesId');
                        var val = 0;
                        if (typeof qur !== "undefined" && qur.length > 0)
                            val = qur;
                        else
                            val = 0;
                        ctx.CurrentFieldValue = val;
                        return SPFieldNumber_Edit(ctx);
                    }
                }
            }
        },
        OnPostRender: function (ctx) {
            //после загрузки
            var f = ctx.ListSchema.Field[0];
            if (f.Name == "MFCEmployeesId") {
                InputHiden(f, "Field",true);
            }
        },
        ListTemplateType: 10006
    });
});
Функция GetUrlKeyValue читает параметр запроса по имени MFCEmployeesId. 
Если находит значение, то подставляет его в поле вторичного ключа. В свою очередь функция 
InputHiden в событии OnPostRender скрывает поле от глаз пользователей.
Как видите, все очень просто. Самое главное:
1. Передать в строке запроса значение ключа сотрудника.
2. Перед сохранение статуса у сотрудника прочитать соответствующий параметр, где храниться
ключ сотрудника и сохранить его в соответствующем input-е.

Пока все. Я показал, как можно прочитать и сохранить значение вторичного ключа.
В следующий раз я продемонстрирую как можно организовать ссылочную целостность 
на практике. Следите за обновлениями :)

No comments:

Post a Comment