Questo articolo è il quarto di una mini-serie di articoli sull'interfaccia REST di SharePoint 2013 e KnockoutJs:


Negli ultimi tre post, abbiamo visto come sfruttare KnockoutJs e la nuova interfaccia REST di SharePoint 2013 per leggere i dati di una lista, inserirne di nuovi e cancellarne alcuni.
Oggi vedremo come fare una modifica di un elemento già esistente all'interno della lista.

Come nell'ultimo post, partiamo dalla parte Javascript.
Per prima cosa, per effettuare una modifica dobbiamo recuperare l'oggetto da modificare. Questo oggetto, che in generale sarà il risultato di una selezione, nel nostro caso dovrà essere selezionato dall'utente a partire dalla lettura degli elementi di lista effettuata al caricamento della pagina (come abbiamo visto nel primo post della serie).
Se vi ricordate, la query di lettura stampava a video i risultati all'interno di una table. Per prima cosa quindi, dobbiamo inserire all'interno di questa tabella un pulsante d'azione per selezionare un singolo elemento da modificare.

<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="#" data-bind="click: $root.selectForUpdate">EDIT</a> |
<a href="#" data-bind="click: $root.delete">DELETE</a>
</td>
</tr>
</tbody>

Come abbiamo già fatto per la cancellazione, anche in questo caso sfruttiamo il binding "click" di KnockoutJs e leghiamo una funzione del nostro view model all'azione di selezione di un elemento della tabella da parte dell'utente finale.
All'interno del view model, tale funzione non dovrà far altro che sfruttare l'oggetto d'appoggio (osservabile) che abbiamo definito nel precedente post e salvare l'elemento selezionato (il nostro model).

self.selectForUpdate = function (data, event) {

self.currentContact(data);
};

La forza del binding click è tale da permetterci di creare una funzione il cui primo parametro rappresenta il model (il dato vero e proprio) legato alla riga selezionata della nostra tabella.
L'intero model poi viene salvato all'interno della variabile d'appoggio "currentContact", sfruttando la sintassi di KnockoutJs. In questo caso poi, il nostro model è già perfettamente configurato per essere spedito a SharePoint ha già, infatti, la proprietà __type (di cui abbiamo parlato nel precedente post).
Vi ricordo che la variabile d'appoggio è stata precedentemente dichiarata come osservabile ed è proprio per questo che dobbiamo utilizzare tale sintassi.

self.currentContact = ko.observable(new D4S.SP2013.Contact());


Ok, una volta che la nostra variabile d'appoggio è stata valorizzata, KnockoutJs ha già provveduto ad aggiornare la view che abbiamo creato nell'ultimo post della serie per inserire un nuovo elemento. Io ho deciso di sfruttare proprio lo stesso template HTML sia per l'inserimento che per la modifica, ovviamente per farvi un esempio. A riguardo potete fare tranquillamente tutte le vostre scelte.
Vi ricordo la sintassi del template HTML legato alla nostra variabile d'appoggio.
L'ho modificata solo un po' per prevedere sia un pulsante di inserimento che un pulsante di modifica (anche qua ovviamente solo ai fini di un semplice esempio):

<div data-bind="template: { name: 'NewEditTemplate', data: currentContact }"></div>   


<script id="NewEditTemplate" type="text/html">
<div>
<input type="text" data-bind="value: Title" placeholder="Insert last name ..." />
</div>
<div>
<input type="text" data-bind="value: FirstName" placeholder="Insert first name ..." />
</div>
<div>
<input type="text" data-bind="value: Email" placeholder="Insert e-mail address ..." />
</div>
<button data-bind="click: $root.insert">New contact</button>
<button data-bind="click: $root.update">Edit contact</button>
</script>

Questo permette all'utente di modificare i valori del contatto selezionato dalla griglia e, allo stesso tempo, permette a noi di avere sempre aggiornato il relativo model all'interno della nostra variabile d'appoggio, per poi spararlo a SharePoint.
Come viene mantenuto aggiornato? Se ne occupa KnockoutJs, noi non dobbiamo fare niente.
Le proprietà del model sono state dichiarate come osservabili, il template è stato legato alla variabile d'appoggio tramite il binding "template" e dalla view è stato creato un binding per legare il valore di tutte le proprietà ai relativi campi di input.

Ok, vediamo come persistere queste modifiche (che per ora sono nella memoria volatile del browser) anche all'interno della lista SharePoint 2013.

self.update = function () {

$.ajax({
url: self.webUrl.SPItemByIdFromList('Contacts', self.currentContact().Id()),
type: 'POST',
data: ko.mapping.toJSON(self.currentContact()),
contentType: self.requestContentType,
headers: {
'content-type': self.requestContentType,
'Accept': self.requestContentType,
'X-RequestDigest': self.digest,
'X-HTTP-Method': 'MERGE',
'IF-MATCH': '*'
},
success: function (data) {
self.currentContact(new D4S.SP2013.Contact());
self.read();
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
};

Per effettuare una modifica ad un elemento di una lista sfruttando le API REST di SharePoint 2013, dobbiamo creare una richiesta HTTP che segua queste regole:
  • La chiamata deve essere fatta alla URL che rappresenta l'elemento che vogliamo modificare (così come abbiamo fatto per la cancellazione):
    • /_api/web/lists/getByTitle('Contacts')/items/(ID)
    • La chiamata deve essere fatta in POST
  • Tra gli header della chiamata, dobbiamo passare:
  • Passare come contenuto della richiesta, l'oggetto che vogliamo inserire nella lista SharePoint

Il parametro X-HTTP-Method='MERGE' dice a SharePoint che quell'elemento va modificato.
Il parametro IF-MATCH serve invece per gestire la concorrenza e il versioning degli element, come abbiamo già spiegato in uno dei precedenti post.. Nell'esempio l'abbiamo messo IF-MATCH=*', che impone a SharePoint di effettuare l'operazione di modifica in qualsiasi caso, anche nel caso in cui il server riscontra dei conflitti. Come se fosse un force.
In caso di successo ci basta creare un'istanza vuota di un oggetto di tipo "Contact" all'interno della variabile d'appoggio ed effettuare una lettura per aggiornare la tabella di contatti.

Conclusione
Bene, siamo arrivati alla fine di questa mini-serie di post su come sfruttare KnckoutJs e le nuove API REST di SharePoint 2013 per effettuare query CRUD su liste.
Diciamo che queste sono le nozioni di base per utilizzare questa libreria con le nuove API esposte da SharePoint. Nozioni che vi possono essere utili sia per lo sviluppo di farm solution sia se vi volete addentrare all'interno del nuovo App-model.

Vi ricordo che potete vedere l'esempio in funzione scaricando il progetto d'esempio che ho creato:
- D4S.SP2013.FrontEndCRUD.zip (1.8 MB)