Nel precedente post abbiamo un po' introdotto JavaScript e KnockoutJs. Oggi vedremo come sfruttare queste tecnologie e fare delle query ai servizi REST di SharePoint 2013.
Dei servizi REST ne abbiamo parlato già tanto. Abbiamo visto anche il codice JavaScript che, tramite JQuery, ci permette di richiamarli ed utilizzarne le funzionalità. Quello che ci manca è come mettere insieme i pezzi e cercare di scrivere la nostra prima "applicazione di frontend" che, dal punto di vista di uno sviluppatore SharePoint, può essere sia una Web Part posta all'interno di una farm solution, che un'App del nuovo App-Model introdotto da SharePoint 2013 che, più semplicemente, un po' di codice inserito in una Content Editor Web Part (nell'esempio, io ho utilizzato un'App).
Vi ricordo solo che per far funzionare il codice che vedremo durante il post, è necessario aggiungere alla propria soluzione (e ovviamente anche in pagina), le seguenti librerie JavaScript:


Bene, per prima cosa creiamo un nuovo file JavaScript e definiamo il nostro ViewModel, ossia la classe che si occupa di fornire i dati (il nostro Model) all'interfaccia (la nostra View).
KnockoutJs ci mette a disposizione due particolari funzioni che ci danno la possibilità di definire delle proprietà del nostro ViewModel "osservabili", cioè che un loro cambiamento può scatenare un cambiamento dell'interfaccia.

window.D4S = window.D4S || {};

window.D4S.SP2013 = window.D4S.SP2013 || {};

window.D4S.SP2013.CrudSampleViewModel = function () {
var self = this;

self.webUrl = D4S.SP2013.Utils.Current.GetQueryString('SPAppWebUrl');
self.requestContentType = 'application/json;odata=verbose';
self.contacts = ko.observableArray([]);
self.isLoadingData = ko.observable();

//... };

Come vedete, il nostro ViewModel espone due proprietà osservabili ("contacts" e "isLoadingData") definite rispettivamente utilizzando le funzioni ok.observable(), utilizzata per una variabile normale, e ko.observableArray([]), utilizzata invece per un'array di elementi.
Per fare in modo che il nostro ViewModel valorizzi correttamente tali proprietà, dobbiamo scrivere il codice per effettuare la nostra query di lettura all'interfaccia REST esposta da SharePoint 2013, così da recuperare tutti gli elementi di un'ipotetica lista di contatti.

window.D4S = window.D4S || {};

window.D4S.SP2013 = window.D4S.SP2013 || {};

window.D4S.SP2013.CrudSampleViewModel = function (digest) {
var self = this;

self.webUrl = D4S.SP2013.Utils.Current.GetQueryString('SPAppWebUrl');
self.requestContentType = 'application/json;odata=verbose';
self.contacts = ko.observableArray([]);
self.isLoadingData = ko.observable();

self.read = function () {
self.isLoadingData(true);
self.contacts.removeAll();
$.ajax({
url: self.webUrl.SPItemsFromList('Contacts').SPSelect('Id', 'Title', 'FirstName', 'Email'),
type: 'GET',
contentType: self.requestContentType,
headers: { 'Accept': self.requestContentType },
cache: false,
success: function (data) {
$.each(data.d.results, function (index, item) {
self.contacts.push(ko.mapping.fromJS(item));
});
self.isLoadingData(false);
},
error: function (jqXHR, textStatus, errorThrown) {
self.isLoadingData(false);
alert(errorThrown);
}
});
};
};

Per generare la URL di richiesta al servizio REST ho utilizzato la mia libreria SharePoint 2013 REST Js Helper, che potete trovare su NuGet, mentre per la chiamata ho utilizzato il metodo "ajax" di JQuery, come abbiamo già visto in uno dei precedenti post.
Molto interessante è l'utilizzo della funzione ko.mapping.fromJS che crea un nuovo oggetto con proprietà "osservabili" a partire da un normalissimo oggetto JavaScript, così che gli oggetti ritornati dalla chiamata al servizio REST siano già in grado di essere legati alla UI tramite dei binding.

Benissimo, così il nostro ViewModel è già pronto.
Come vi dicevo, la bellezza di questa pattern è che ci permette la scrittura della logica di business totalmente staccata dalla scrittura della UI.
Passiamo all'interfaccia quindi.
L'obbiettivo è quello di stampare la lista dei contatti all'interno di una semplice tabella. Per farlo, possiamo sfruttare i binding di KnockoutJs in questo modo:

<h1>Contacts</h1>

<table>
<thead>
<tr>
<th>Last name</th>
<th>First name</th>
<th>E-mail</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: { data: contacts }">
<tr>
<td>
<span data-bind="text: Title"></span>
</td>
<td>
<span data-bind="text: FirstName"></span>
</td>
<td>
<span data-bind="text: Email"></span>
</td>
<td>
<a href="#">EDIT</a> | <a href="#">DELETE</a>
</td>
</tr>
</tbody>
</table>
<div class="loader" data-bind="visible: isLoadingData"><img src="loader.gif" /></div>

Il binding più interessante è il binding "foreach", che per ogni elemento presente nell'array a cui viene associato, renderizza in pagina il codice HTML specificato come figlio dell'elemento in cui è stato definito il binding (nel nostro caso, viene ripetuto il codice che crea una riga della tabella).
Inoltre, è possibile vedere come, tramite il binding "text" siamo in grado di definire il template di elemento, specificando quali proprietà del singolo oggetto dell'array vogliamo stampare a video.
Altro binding interessanto è poi il vinding "visible", che ho utilizzato per nascondere o visualizzare un'immagine di caricamento dati, in base al comportamento della chiamata alle api REST di SharePoint 2013. Il tutto settando semplicemente una variabile da false a true, e viceversa.
Altra cosa fantastica è che avendo inserito l'intero array risultato dalla chiamata REST alla lista SharePoint 2013, abbiamo la possibilità di specificare, in fase di binding (quindi nell'HTML), tutte le proprietà tramite il loro InternalName (es: "Title", "FirstName" ed "Email", che sono tutti i campi di default di una lista creata con il template "Contacts").
Bene, ci manca solo di legare la nostra View (il codice HTML che abbiamo appena visto) al nostro ViewModel (una nuova istanza delle classe CrudSampleViewModel).
Questa operazione la possiamo fare al load della pagina, quando il documento è stato renderizzato, tramite il metodo "applyBindings" esposto da KnockoutJs.

$(document).ready(function () {

var model = new D4S.SP2013.CrudSampleViewModel();
ko.applyBindings(model);

model.read();
});

Ecco che abbiamo implementato la lettura dei dati risultati da una query REST a SharePoint 2013 all'interno di una nostra applicazione di front-end.
Nei prossimi post vedremo come fare inserimento, aggiornamenti e cancellazioni.