Gestione dell'abilitazione di un bottone sulla ribbon in base al content type (SharePoint 2010)
Come illustrato in Deploy di una custom action nella ribbon è possibile aggiungere dei bottoni sulla ribbon di SharePoint 2010 legati ad uno specifico content type.
L'abilitazione o meno del bottone è controllata tramite l'attributo EnabledScript della sezione CommandUIHandlers.
Nel caso si volesse abilitare il bottone solo quando si seleziona un solo item la cosa è semplice:
conto gli item selezionati e restituisco true se ho un solo elemento.
Se però nella lista ho più content type e voglio abilitare la visualizzazione sull'item solo su uno specifico content type... la cosa si complica.
Infatti nella variabile items non ho niente che mi dice quale content type è associato ad ogni item. questo significa che devo fare una chiamata asincrona, tramite il modello ad oggetti JavaScript, a SharePoint per recuperare il content type associato all'item.
Qui un esempio:
Come funziona?
Prima di tutto mi assicuro di avere una array window.enableSgartCmd_EditId globale per mantenere lo stato tra le chiamate asincrone e il refresh della ribbon.
Poi, se ho un solo elemento selezionato, faccio una chiamata asincrona (enableSgartCmdEdit_GetCT) per farmi ritornare il content type associato all'item corrente. Essendo la chiamata asincrona l'unica cosa che posso fare, non avendo ancora il content type, è restituire false e lasciare il pulsante disabilitato.
Nella funzione enableSgartCmdEdit_GetCT costruisco la chiamata asincrona, quando arriva la riposta controllo se il content type è quello che volevo e imposto la variabile globale (enableSgartCmd_EditId[id]) a true. A questo punto l'unico modo che ho per aggiornare la ribbon è invocare la chiamata RefreshCommandUI che esegue tutte le funzioni definite nell'attributo EnabledScript di tutti i bottoni della ribbon.
A questo punto lo script viene eseguito di nuovo, ma trovando un valore nell'array enableSgartCmd_EditId, indicizzato tramite l'id dell'item, non esegue la chiamata asincrona, ma resituisce il valore true o false memorizzato immediatamente.
Ovviamente ci sarà un piccolo ritardo nell'abilitazione del pulsante la prima volta che viene selezionato.
L'abilitazione o meno del bottone è controllata tramite l'attributo EnabledScript della sezione CommandUIHandlers.
Nel caso si volesse abilitare il bottone solo quando si seleziona un solo item la cosa è semplice:
XML
<CommandUIHandler
Command="Sgart_Cmd_Edit"
CommandAction="javascript:..."
EnabledScript="javascript:
function enableSgartCmdEdit()
{
var items = SP.ListOperation.Selection.getSelectedItems();
return (items.length == 1);
}
enableSgartCmdEdit();"
/>
</CommandUIHandlers>
Se però nella lista ho più content type e voglio abilitare la visualizzazione sull'item solo su uno specifico content type... la cosa si complica.
Infatti nella variabile items non ho niente che mi dice quale content type è associato ad ogni item. questo significa che devo fare una chiamata asincrona, tramite il modello ad oggetti JavaScript, a SharePoint per recuperare il content type associato all'item.
Qui un esempio:
XML
<CustomAction Id="SgartEditRibbon"
RegistrationType="ContentType"
RegistrationId="0x01012BB0B1C886E8415AB34C2B11C7B3CBE6"
Location="CommandUI.Ribbon.ListView"
Title="Edit Questions">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition Location="Ribbon.ListItem.Actions.Controls._children">
<Button Id="Ribbon.Items.Actions.EditQuestion"
Sequence="100"
Command="Sgart_Cmd_Edit"
Image32by32="~site/_layouts/images/CRIT_32.GIF"
Image16by16="~site/_layouts/images/CRIT_16.GIF"
LabelText="Edit Questions"
TemplateAlias="o1" />
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler
Command="Sgart_Cmd_Edit"
CommandAction="javascript:location.href='{SiteUrl}/_Layouts/sgart/Edit.aspx?SgartID={SelectedItemId}&Source={Source}'"
EnabledScript="javascript:
function enableSgartCmdEdit()
{
if(window.enableSgartCmd_EditId === undefined){
window.enableSgartCmd_EditId = [];
}
var items = SP.ListOperation.Selection.getSelectedItems();
if(items.length == 1) {
var id = items[0].id;
if(enableSgartCmd_EditId[id] === undefined){
enableSgartCmdEdit_GetCT(id);
}else{
return enableSgartCmd_EditId[id];
}
}else{
return false;
}
}
function enableSgartCmdEdit_GetCT(id){
var context = SP.ClientContext.get_current();
var web = context.get_web();
var listId = SP.ListOperation.Selection.getSelectedList();
var list = web.get_lists().getById(listId)
var item = list.getItemById(id);
context.load(item, 'ContentTypeId');
context.executeQueryAsync(function(sender, args) {
var correctContentTypeId = ['0x01012BB0B1C886E8415AB34C2B11C7B3CBE6', '0x0100E06DF65DF9564DDB9AA297084E500608'];
var contentTypeId = item.get_item('ContentTypeId').toString();
if (contentTypeId.indexOf(correctContentTypeId[0]) == 0
//|| contentTypeId.indexOf(correctContentTypeId[1]) == 0
)
{
enableSgartCmd_EditId[id] = true;
} else {
enableSgartCmd_EditId[id] = false;
}
RefreshCommandUI();
}, function(sender, args) {
alert(args);
}
);
}
enableSgartCmdEdit();
"
/>
</CommandUIHandlers>
</CommandUIExtension>
</CustomAction>
Prima di tutto mi assicuro di avere una array window.enableSgartCmd_EditId globale per mantenere lo stato tra le chiamate asincrone e il refresh della ribbon.
Poi, se ho un solo elemento selezionato, faccio una chiamata asincrona (enableSgartCmdEdit_GetCT) per farmi ritornare il content type associato all'item corrente. Essendo la chiamata asincrona l'unica cosa che posso fare, non avendo ancora il content type, è restituire false e lasciare il pulsante disabilitato.
Nella funzione enableSgartCmdEdit_GetCT costruisco la chiamata asincrona, quando arriva la riposta controllo se il content type è quello che volevo e imposto la variabile globale (enableSgartCmd_EditId[id]) a true. A questo punto l'unico modo che ho per aggiornare la ribbon è invocare la chiamata RefreshCommandUI che esegue tutte le funzioni definite nell'attributo EnabledScript di tutti i bottoni della ribbon.
A questo punto lo script viene eseguito di nuovo, ma trovando un valore nell'array enableSgartCmd_EditId, indicizzato tramite l'id dell'item, non esegue la chiamata asincrona, ma resituisce il valore true o false memorizzato immediatamente.
Ovviamente ci sarà un piccolo ritardo nell'abilitazione del pulsante la prima volta che viene selezionato.