Serie di post sullo SharePoint Framework
- SharePoint Framework: la struttura di una Client Side Web Part
- SharePoint Framework: la classe Web Part (questo post)

Nei precedenti post abbiamo visto la struttura di un progetto creato con gli strumenti offerti dallo SharePoint Framework, assieme alla struttura di cartelle e file a comporre una nuova Client Side Web Part.
Oggi vedremo la sintassi e i costrutti di base della classe TypeScript che rappresenta la nostra web part.

Ecco come si presenta una Client Side Web Part, creata senza specificare alcun tipo di framework Javascript di supporto:

import {
  BaseClientSideWebPart,
  IPropertyPaneSettings,
  IWebPartContext,
  PropertyPaneTextField
} from '@microsoft/sp-client-preview';

import styles from './HelloWorld.module.scss';
import * as strings from 'helloWorldStrings';
import { IHelloWorldWebPartProps } from './IHelloWorldWebPartProps';

export default class HelloWorldWebPart extends BaseClientSideWebPart<IHelloWorldWebPartProps> {

  public constructor(context: IWebPartContext) {
    super(context);
  }

  public render(): void {
    this.domElement.innerHTML = '
      <div class="${styles.helloWorld}">
        <div class="${styles.container}">
          <div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}">
            <div class="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
              <span class="ms-font-xl ms-fontColor-white">Welcome to SharePoint!</span>
              <p class="ms-font-l ms-fontColor-white">Customize SharePoint experiences using Web Parts.</p>
              <p class="ms-font-l ms-fontColor-white">${this.properties.description}</p>
              <a href="https://github.com/SharePoint/sp-dev-docs/wiki" class="ms-Button ${styles.button}">
                <span class="ms-Button-label">Learn more</span>
              </a>
            </div>
          </div>
        </div>
      </div>`;
  }

  protected get propertyPaneSettings(): IPropertyPaneSettings {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('description', {
                  label: strings.DescriptionFieldLabel
                })
              ]
            }
          ]
        }
      ]
    };
  }
}

Cerchiamo di analizzarne le parti principali.
Per prima cosa notiamo la sezione degli "import". Esattamente come con lo "using" di C#, abbiamo modo di inserire la referenza a file, classi o interi moduli (namespace) per utilizzarne gli oggetti definiti al loro interno.

import {
  BaseClientSideWebPart,
  IPropertyPaneSettings,
  IWebPartContext,
  PropertyPaneTextField
} from '@microsoft/sp-client-preview';

import styles from './HelloWorld.module.scss';
import * as strings from 'helloWorldStrings';
import { IHelloWorldWebPartProps } from './IHelloWorldWebPartProps';

Nel caso di una Client Side Web Part, si importano:
  • Le classi di base delle librerie dello SharePoint Framework (@microsoft/sp-client-preview)
  • Gli stili CSS presenti nel file SASS del nostro progetto
  • Le variabili per la localizzazione delle label
  • L'interfaccia TypeScript contenente le proprietà della web part
Tra le classe importate dalle librerie dello SharePoint Framework vediamo:
  • BaseClientSideWebPart - Classe base di tutte le Client Side Web Part (un pò come la classe WebPart delle Farm Solution)
  • IPropertyPaneSettings - Interfaccia utile al funzionamento del nuovo pannello di proprietà delle Client Side Web Part
  • IWebPartContext - Interfaccia utile a recuperare informazioni dal contesto corrente (es: nome del sito SharePoint, utente corrente, ecc..)
  • PropertyPaneTextField - Classe utile alla creazione di proprietà della web part, in formato "singola riga di testo"
Successivamente notiamo la sintassi TypeScript per la definizione di una classe.

export default class HelloWorldWebPart extends BaseClientSideWebPart<IHelloWorldWebPartProps> {
  public constructor(context: IWebPartContext) {
    super(context);
  }

  //codice nascosto per leggibilità
}

Così facendo abbiamo definito la nostra Client Side Web Part e possiamo sfruttare le funzionalità della classe base, per la nostra implementazione. Il costruttore pubblico ci serve per recuperare il contesto corrente.
La classe BaseClientSideWebPart è un generico, che viene utilizzata per specificare le proprietà della web part. Passando infatti il nome dell'interfaccia IHelloWorldWebPartProps, stiamo dicendo al compilatore TypeScript e agli strumenti di build dello SharePoint Framework che la nostra web part avrà come proprietà tutte quelle definite all'interno dell'interfaccia specificata.

Subito dopo troviamo il primo e unico metodo che è presente all'interno della classe, al momento della creazione del nuovo progetto: il metodo render. Questo metodo è molto importante, in quanto viene richiamato dal sistema di rendering di SharePoint, per renderizzare la nostra web part.

  //codice nascosto per leggiblità

  public render(): void {
    this.domElement.innerHTML = '';
  }

  //codice nascosto per leggiblità

All'interno di questo metodo, il nostro unico compito è quello di valorizzare la proprietà domElement con il codice HTML che vogliamo essere visualizzato a video.
La cosa che deve essere chiara è che le Client Side Web Part sono state implementate in modo tale da essere reattive (ancora non centra niente ReactJs), cioè che alla modifica del valore di una proprietà la loro visualizzazione viene aggiornata in automatico, senza la necessità di un refresh della pagina.
Come accade tutto ciò? Molto semplice: ad ogni modifica del valore di qualsiasi proprietà di una web part, viene richiamato il metodo render della web part stessa.
E' proprio per questo che dobbiamo far attenzione al codice che inseriamo all'interno di questo metodo. 

Infine, troviamo la proprietà "propertyPaneSettings", che viene utilizzata per specificare il contenuto del pannello delle proprietà della web part (un pò come si faceva con il ToolPane di una web part all'interno delle Farm Solution).

    //codice nascosto per leggibilità

    protected get propertyPaneSettings(): IPropertyPaneSettings {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('description', {
                  label: strings.DescriptionFieldLabel
                })
              ]
            }
          ]
        }
      ]
    };

    //codice nascosto per leggibilità

Questa proprietà, con il solo selettore get, abbiamo il pieno controllo per la definizione del pannello delle proprietà della nostra web part, potendo quindi specificare:
- Il numero di pagine da rendere disponibili all'interno del pannello
- I gruppi di proprietà, per ognuna di queste pagine
- Le singole proprietà, per ognuno di questi gruppi
- La tipologia di proprietà per ognuna delle proprietà definite all'interno dell'interfaccia IHelloWorldWebPartProps (in pratica, qui definiamo se visualizzare delle singole caselle di testo, delle drop down list, delle checkbox, degli slider, ecc..)

Bene, questo è il template di default proposto da Microsoft.
Da qui in poi siete liberi di partire con la vostra implementazione ;)