среда, 9 октября 2013 г.

Client-side rendering представления списка

Здесь подробный доклад о Client Side Rendering! С него всё и началось...

В SharePoint 2013 появилась новая возможность кастомизации, которая носить общее название Client-side rendering. Заключается она в том, что теперь генерацией HTML разметки некоторых компонентов SharePoint  можно управлять на стороне клиента. Т.е. в браузере пользователя с помощью JavaScript.
К объектам, которые поддерживают такого рода кастомизацию, добавилось новое свойство JSLink.

Рассмотрим Client-side rendering кастомизацию на примере представление списка!

Представление списка (list view), с точки зрения объектной модели SharePoint, является объектом типа SPView. В SharePoint 2013 в SPView добавилось новое свойство JSLink. Это свойство содержит ссылку на JavaScript файл. В котором мы можем написать код, который будет вызван стандартными методами SharePoint'а и использован для генерации необходимой HTML-разметки.


Таким образом, в SharePoint 2013 появилась новая возможность с лёгкостью кастомизировать стандартное представление списка. Например, с помощью простого javascript кода, мы можем заменить следующее стандартное представление списка:
На такое:
В принципе очень удобно.

Рассмотрим эту новую технику подробнее.
Вот JavaScript, который я использовал:

var _;
(function (_) {
    function init() {
        // Создаём объект (для удобства, назовём его RenderTemplate), в котором описываются параметры переопределения стандартных методов SharePoint используемых для генерации HTML-разметки представления списка
        var templateOptions = {};

        // Задаём условия применения нашего RenderTemplate.
        // RenderTemplate будет применятся только к тем спискам, которые были созданы на основе указанного ListTemplateType.
        templateOptions.ListTemplateType = 16606;

        // Задаём вьюшку списка, к которой будет применятся данный RenderTemplate
        templateOptions.BaseViewID = 2;

        // Задаём функции, которые будут использоваться для генерации соответсвующей HTML разметки.
        templateOptions.Templates = {};
        templateOptions.Templates.Footer = QuickPhonesFooter;
        templateOptions.Templates.Header = QuickPhonesHeader;
        templateOptions.Templates.Item = QuickPhonesItem;
       
        // Регистрируем наш RenderTemplate в TemplateManager
        SPClientTemplates.TemplateManager.RegisterTemplateOverrides(templateOptions);
    }
    ;
   
    function QuickPhonesHeader(renderContext) {
        var listTitleArray = renderContext.ListTitle.split(" ");
        var listTitle = listTitleArray[0];
        for (var i = 1; i < listTitleArray.length; i++) {
            listTitle = listTitle + "<br/>" + listTitleArray[i];
        }
   
        return "<div class='heading_color_perple' >" + listTitle + "</div><div class='MayListViewScrolling'>";
    }

    function QuickPhonesItem(renderContext) {
        if (renderContext.CurrentItem.Title != undefined) {
            var result = "<div class='phone_item' >";
            result = result + "<span class='phone_type'>" + renderContext.CurrentItem.Title + "</span>";

            var name = "";
            if (renderContext.CurrentItem.QuickPhones_Contact[0] != undefined) {
                result = result + "<span class='phone_name'>" + renderContext.CurrentItem.QuickPhones_Contact[0].title + "</span>";
            }

            result = result + "<span class='phone_num'>" + renderContext.CurrentItem.QuickPhones_Phones + "</span>";

            return result + "</div>";
        }
        return "";
    }
   
       
    function QuickPhonesFooter(renderContext) {
        return "</div>";
    }
   
    init();
})(_ || (_ = {}));
;

Здесь нас интересует функция init(). В ней задаются параметры переопределения стандартных SharePoint'овских методов для генерации HTML разметки, своими собственными. Параметры переопределения задаются с помощью templateOptions, и затем регистрируются с помощью метода RegisterTemplateOverrides.
Нас интересует как будет переопределяется  templateOptions в тех или иных случаях.
Параметр ListTemplateType
Сначала SharePoint смотрит на основе какого шаблона был создан текущий список. Если тип шаблона совпадает с типом шаблона, который указан в templateOptions.ListTemplateType, значит этот templateOptions в принципе применим к данному списку.
Причем, если в JavaScript коде, для templateOptions.ListTemplateType вы ничего не указали, то SharePoint решит, что данные templateOptions в принципе применимы к любому списку, независимо от того, на основе какого шаблона он был создан.
(Тип шаблона списка можно посмотреть в свойстве SPList.BaseTemplate)
Параметр BaseViewID
Далее SharePoint'у необходимо выяснить, можно ли применять templateOptions к текущему представлению списка. Для этого SharePoint'ом проверяет BaseViewID текущего представления списка. Если оно равно  templateOptions.BaseViewID, значит методы указанные в templateOptions  сработают при генерации HTML-разметки.
Причём опять-таки, если  для templateOptions.BaseViewID вы ничего не указали, то SharePoint решит, что данные templateOptions в принципе применимы к любому представлению данного списка.
(BaseViewID это свойство SPView.BaseViewID представление списка)
Параметр  ViewStyle
Наконец, разработчики SharePoint завели ещё один параметр, для конкретизации представления списка. Это свойство  ViewStyle, которое можно задать например таким образом:
       templateOptions.ViewStyle = 20;

По всей видимости, оно должно задавать стиль представления списка. Дело в том, что для представления списка можно задать один из стандартных стилей.

(Стиль текущего представления списка можно посмотреть в свойстве SPView.ViewStyle)
В принципе мы можем изменить стиль списка со значения "По умолчанию" на любое другое. И в теории, если мы задаём параметр ViewStyle в нашем CSR скрипте, то он должен срабатывать и генерить HTML разметку, только в том случае, если стиль текущего представление списка совпадает со значением указанным во ViewStyle.
Это в теории. :-) А на практике мой опыт показал, что CSR срабатывать, только для представления списка со стилем по умолчанию. Во всех остальных случаях JavaScript файл используемый для CSR, даже не подгружается на страницу.
Не смотря на то, что у Microsoft предусмотрен параметр templateOptions.ViewStyle, он в принципе бесполезен для наших целей. Единственно, что вы можете реально сделать, это присвоить свойству templateOptions.ViewStyle какое-нибудь значение и тем самым "сломать" работу вашего CSR-скрипта.

Особенности использования CSR
CSR и стандартные списки
CSR в принципе применим к любым спискам SharePoint. Достаточно заменить стандартное значение свойства JSLink, любого представления, любого списка, на своё собственное.

Например, пусть у вас есть одна ASPX страница (например, стандартная страница представления списка), на которой кроме веб-части с представлением списка больше ни чего нет. Тогда всё пройдёт просто прекрасно. Главное правильно задать параметры переопределения RenderTemplate в JavaScript'е.

Однако, что если у вас есть некая страница веб-частей, на которой размещено сразу несколько однотипных списковНапример, кто-то создал парочку стандартных настраиваемых списков. Причём один является списком готовых товаров, а другой списком комплектующих. И вам нужно, чтобы список товаров рендерился иначе, нежели список комплектующих.
Что ж, тогда у вас есть маленькая проблемка. :-)

Оба списка, созданы по одному и тому же шаблону - шаблону настраиваемых списков. Более того, все представления списков имеют одно и тоже значение BaseViewID = 1. И это значение доступно только для чтения.
Таким образом RenderTemplate одного списка, переопределит RenderTemplate  другого списка. Ведь у них одни и те же параметры ListTemplateType и BaseViewID. В результате оба списка будут отображаться одинаково.
Пожалуй, самый правильный способ избежать таких проблем, это создавать свои собственные шаблоны списков, для тех списков, в которых вы планируете применять CSR. Кстати, в шаблоне списка (в файле Schema.xml) также можно задать значение BaseViewID отличное от 1.

Такое решение хорошо смотрится в SharePoint on premises. Его также можно применять и для SharePoint в облаке. Ведь оно поддерживает sandbox solutions, с помощью которых можно легко развернуть собственный шаблон списка.

Остаётся открытым вопрос, как всё это будет работать в будущем.

CSR и внешние списки (external lists)
Разбираясь с CSR на практике, я столкнулся с необходимостью разметить на одной странице сразу две веб-части с внешними списками. (Внешние списки - это списки, которые используются для отображения контента из внешнего источника данных. Например, из базы данных MS SQL)

Оба списка были созданы с помощью SharePoint Designer по одному и тому же встроенному шаблону внешних списков (т.е. templateOptions.ListTemplateType = 600). Все представления обоих этих списков имеют BaseViewID = 1. Так как для создания представлений использовался стандартный GUI.

Первое что я решил сделать, это кастомизировать представления одного из списков. Однако кастомизации поддавалось только представление списка созданное по умолчанию. Для остальных представлений списка файл из SPView.JSLink, просто не подгружался.

Какой-то явный баг!
Благо свойство JSLink есть не только у объекта SPView, но и у соответствующей веб-части. Достаточно взглянуть на свойства этой веб части и найти параметр JS-ссылка.
 После того, как ссылка на JavaScript файл были размещена в свойствах веб-части, всё заработало.

Следующей особенностью работы CSR с внешними списками, стал тот факт, что CSR не работает, если представление внешнего списка (ИМЕННО ВНЕШНЕГО СПИСКА!) размещается на Publishing page! 
Причём работать перестаёт только после публикации страницы. До тех пор, пока страница не опубликована, т.е. сохранена как черновик, всё работает нормально.

Я решил эту проблемы просто тем, что отказался от использования  Publishing page в пользу обычной Web part page.

Остался открытым вопрос относительно того. Как же всё-таки  разместить два внешних списка на одной Web part page? Ведь CSR скрипт одного списка, обязательно переопределит другой.
К сожалению, тут пришлось пойти на хард-код. Представления обоих списков ссылаются на один и тот же JavaScript файл. А методы отвечающие за генерацию соответствующей HTML разметки просто проверяют название текущего списка и в зависимости от этого генерируют ту или иную строку с HTML кодом.

Комментариев нет:

Отправить комментарий