- PVSM.RU - https://www.pvsm.ru -
Прошлый раз [1] я описывал преимущества использования TypeScript для разработки приложений.
В этом посте я покажу как TypeScript поможет разрабатывать приложения для SharePoint 2013. В SharePoint 2013 были улучшены возможности разработки клиентских приложений на JavaScript. Это касается не только API, доступных на клиенте, но и механизмов поставки и развертывания приложений, инструментов разработчика. Более того, многие функции самого SharePoint 2013 реализованы и могу быть кастомизированы с помощью JavaScript.
SharePoint 2013 предлагает два вида API для использования на клиентской стороне: Client-Side Object Model (CSOM) и REST API. REST API позволяет манипулировать объектами на сервере используя REST (OData) веб-сервис. CSOM представляет из себя набор классов, семантически эквивалентных серверной объектной модели SharePoint. CSOM доступна как для JavaScript (также называют JSOM – JavaScript Object Model), так и для .NET. Но в JavaScript, в отличие от .NET, недоступны метаданные и типизация. В этой статье будет рассмотрено именно применение JSOM.
TypeScript позволяет описать типы для JSOM и использовать статическую проверку типов и intellisense при разработке приложений. К сожалению готовых определений типов для SharePoint 2013 в открытом доступе нет.
Я и Андрей Маркеев [2]создали проект на CodePlex, в котором сделали определения типов и кучу примеров приложений на TypeScript для SharePoint 2013. Ссылка на проект — http://sptypescript.codeplex.com/ [3]
Для примера создам приложение, позволяющее отслеживать время на рабочем месте.

Для начала необходимо:
Для того чтобы при сборке проекта выполнялась компиляция TypeScript необходимо добавить в .csproj файл следующие элементы:
<PropertyGroup>
<TypeScriptTarget>ES3</TypeScriptTarget>
<TypeScriptIncludeComments>true</TypeScriptIncludeComments>
<TypeScriptSourceMap>true</TypeScriptSourceMap>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)MicrosoftVisualStudiov$(VisualStudioVersion)TypeScriptMicrosoft.TypeScript.targets" />
Визуальный интерфейс будет создан с помощью библиотеки knockoutjs с расширением koLite.
Для того чтобы использовать эти библиотеки в проекте необходимо добавить следующие NuGet пакеты:
Последние три пакета представляют из себя .d.ts файлы, которые описывают типы для TypeScript.
Для работы с JSOM в TypeScript надо добавить в проект файл SharePoint.d.ts, который можно найти по ссылке [8]. NuGet пакет будет доступен в ближайшее время.
Загрузка скриптов по требованию
В SharePoint есть свой загрузчик скриптов по требованию в классе SP.SOD. Подробное описание можно найти в этом посте [9].
Код загрузчика скриптов приложения:
///<reference path="typings/SharePoint.d.ts" />
///<reference path="typings/jquery/jquery.d.ts" />
///<reference path="typings/knockout/knockout.d.ts" />
/// <reference path="ViewModel.ts" />
$(() => {
SP.SOD.registerSod('ViewModels', _spPageContextInfo.webServerRelativeUrl + '/Scripts/ViewModel.js');
SP.SOD.registerSodDep('ViewModels', 'sp.js');
SP.SOD.executeFunc('ViewModels', null, () => {
var vm = new ViewModels.Model(SP.ClientContext.get_current());
ko.applyBindings(vm);
});
});
Разметка страницы приложения:
<div>
<p data-bind="text:message"></p>
<button data-bind="text:buttonText, command: checkInOut, visible:isLoaded" style="display:none;"/>
</div>
Используется плагин koLite [10] для асинхронных команд.
Код модели представления:
module ViewModels {
export class Model {
constructor(public context: SP.ClientContext) {
this.isLoaded = ko.observable(false);
this.message = ko.observable('');
this.buttonText = ko.observable('');
this.checkInOut = ko.asyncCommand({
canExecute: (isExecuting) => !isExecuting && this.isLoaded(),
execute: this.executeCheckInOut
});
this.init();
}
public message: KnockoutObservableString;
public buttonText: KnockoutObservableString;
public checkInOut: KoliteCommand;
public isLoaded: KnockoutObservableBool;
//...
}
}
Все типы описаны в .d.ts файлах и проверяются при компиляции.Инициализация модели
JSOM при выполнении формирует очередь команд, отправляемых на сервер функцией SP.ClientContext.executeQueryAsync. executeQueryAsync принимает два коллбека, первый вызывается в случае успешного завершения, второй в случае неудачи. Внимание, указатель this портится внутри коллбеков функции executeQueryAsync, но если указывать коллбеки в виде лямбд, то TS заботливо генерирует код, который сохраняет указатель this.
private init() {
this.list = this.context.get_web().get_lists().getByTitle('Log');
var items = this.list.getItems(SP.CamlQuery.createAllItemsQuery());
this.context.load(items);
this.context.executeQueryAsync(
() => {
this.processItems(items);
this.setData();
this.isLoaded(true);
},
(sender, args) => alert(args.get_message()));
};
Запрос множества элементов в JSOM возвращает не массив, а коллекцию объектов, реализующую интерфейс IEnumerable, хотя внутри объекта лежит массив. Это все вызвано тем, что большая часть клиентской объектной модели сгенерирована из серверной объектной модели, и все коллекции требуют специальный паттерн для обхода. Он 100% соответствует коду .NET для обработки IEnumerable коллекций.
Обработка результатов запроса:
private processItems(items: SP.ListItemCollection) {
this.hoursSubmitted = 0;
var enumerator = items.getEnumerator();
while (enumerator.moveNext()) {
var item = <SP.ListItem>enumerator.get_current();
var author = <SP.FieldUserValue>item.get_item('Author');
//Filter by current user
if (author.get_lookupId() == _spPageContextInfo.userId) {
var dateCompleted = item.get_item('DateCompleted');
if (dateCompleted) {
this.hoursSubmitted += item.get_item('DurationInHours');
} else {
this.curentItem = item;
}
}
}
}
В коде выше также показано как выполнять приведение типов. TypeScript доверяет всем операциям приведения типов, поэтому вам необходимо следить, чтобы они были корректными.
Обработка команд
В зависимости от текущего состояния модели выполняется Check-In или Check-Out
private executeCheckInOut(complete: () => void ) {
if (this.curentItem) {
this.checkOut(complete);
} else {
this.checkIn(complete);
}
};
Операция Check-In заключается в создании нового элемента в списке SharePoint, без указания времени завершения.
private checkIn(complete: () => void ) {
var item = this.list.addItem(new SP.ListItemCreationInformation());
item.set_item('StartDate', new Date());
item.update();
this.context.executeQueryAsync(
() => {
this.curentItem = item;
this.setData();
complete();
},
(sender, args) => {
alert(args.get_message());
complete();
});
}
Противоположная операция – Check-Out – заполняет значения времени завершения и продолжительности в часах.
private checkOut(complete: () => void ) {
var startedDate = <Date>this.curentItem.get_item('StartDate');
var dateCompleted = new Date();
var hours = (dateCompleted.getTime() - startedDate.getTime()) / (1000 * 60 * 60);
this.curentItem.set_item('DateCompleted', dateCompleted);
this.curentItem.set_item('DurationInHours', hours);
this.curentItem.update();
this.context.executeQueryAsync(
() => {
this.curentItem = null;
this.hoursSubmitted += hours;
this.setData();
complete();
},
(sender, args) => {
alert(args.get_message());
complete();
});
}
В обоих случаях используется один и тот же “паттерн”. Сначала формируется пакет команд для отправки на сервер, а после успешного применения изменения отражаются в модели.
Полный код примера вы можете скачать по ссылке [11]. Также рекомендую посмотреть код проекта и примеры использования определений TypeScript для SharePoint (source code [12]), найдете много интересного.
Кстати сам код примера будет работать и в SharePoint 2010, но придется создать другой проект и по-другому развертывать артефакты решения, чтобы все вместе заработало.
А в следующий раз я расскажу как можно кастомизировать формы и представления списков в SharePoint 2013, и тоже с помощью TypeScript.
Автор: gandjustas
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/sharepoint/30299
Ссылки в тексте:
[1] Прошлый раз: http://habrahabr.ru/post/173813/
[2] Андрей Маркеев : https://twitter.com/amarkeev
[3] http://sptypescript.codeplex.com/: http://sptypescript.codeplex.com/
[4] средства разработки приложений для SharePoint 2013: http://aka.ms/OfficeDevToolsForVS2012
[5] Web Essentials 2012: http://vswebessentials.com/
[6] TypeScript: http://go.microsoft.com/fwlink/?LinkID=266563
[7] создать 90-дневный trial: http://msdn.microsoft.com/en-us/library/office/apps/fp179924(v=office.15)
[8] по ссылке: http://sptypescript.codeplex.com/SourceControl/changeset/view/3cded395d044#SPTypeScript/Definitions/SharePoint.d.ts
[9] этом посте: http://www.ilovesharepoint.com/2010/08/sharepoint-scripts-on-demand-spsod.html
[10] плагин koLite: https://github.com/CodeSeven/kolite
[11] по ссылке: http://sptypescript.codeplex.com/releases/view/103953
[12] source code: http://sptypescript.codeplex.com/SourceControl/BrowseLatest
[13] Источник: http://habrahabr.ru/post/174099/
Нажмите здесь для печати.