Power Apps Component Framework

Tempo di lettura 5 minuti

Power Apps component Framework ( PCF ) apre le porte ad un’ incredibile possibilità di estensione della Power Platform, consentendo di sviluppare componenti custom per power apps canvas, model driven o custom page.

L’obbiettivo di questo articolo è quello di racchiudere l’essenza di questo framework.

Spoiler! Nelle pagine che seguiranno non troverai una guida step by step su come creare il tuo primo componente PCF. 

Dopo una rapida analisi della struttura di un componente metteremo sotto la lente di ingrandimento il ciclo di vita di un componente, analizzando le funzioni principale e come esse interagiscono con il framework a runtime.

Successivamente apriremo una parentesi su React e sui componenti virtual, evidenziando in cosa differisce da un componente standard.

Concluderemo questo articolo affrontando il rilascio di un componente utilizzando Power Platform CLI.

Ma devo proprio usarlo ?

Prima di iniziare a vedere come questo framework lavora proviamo a fare alcune considerazioni sulla sua adozione.

Partiamo da un assunto, il PCF consente di creare qualcosa che non è presente out-of-the-box come ad esempio particolari validazioni o filtri.

Tuttavia la sua adozione deve essere ben valutata perchè ogni componete sviluppato ha un costo di sviluppo e soprattutto di mantenimento.

Inoltre bisogna tenere in considerazione che l’utilizzo di un elevato numero di componenti custom può impattare negativamente in termini di performance soprattutto per applicazioni Canvas.

Capire quindi quanto riusciamo a spingerci con controlli standard è un aspetto fondamentale per l’analisi iniziale.

Tuttavia nel caso in cui utilizzando componenti out-of-the-box lo sviluppo si riveli non pratico da utilizzare e con tempi molto significativi allora il PCF può essere la soluzione.

Pertanto, comprenderne le potenzialità è cosa buona e giusta!

Uno dei primi confronti che si può fare per iniziare ad apprezzare i vantaggi introdotti dal framework è il paragone con una Web Resource.

La prima di differenza, non di certo la più importante ma comunque degna di nota, è che i PCF sono progettati per essere generici, aggiungono un’enorme flessibilità al quadro generale.

Le web resource non sono altrettanto generiche.

Basta pensare alla possibilità di utilizzare alcune proprietà di input come parametri di configurazione, oppure la flessibilità nel lavorare con tabelle.

Bisogna poi tenere in considerazione che alcune API utilizzate frequentemente nelle web resource stanno diventando deprecate. 

Inoltre l’utilizzo del framework consente di sviluppare soluzioni più riusabili, di avere un accesso al context più semplificato e consentire di gestire direttamente nel componente possibili chiamate al server.

Scontato dire che i componenti sviluppati con il framework portano un alto miglioramento delle performance vista anche la possibilità di adottare i moderni framework come React. 

Una volta creato il tuo componente standard, di tipo field oppure dataset con il seguente comando :

pac pcf init -n “name” -ns “namespace” -t [dataset or field ]

ti ritroverai una struttura come quella riportata qui a fianco. 

Il file index.ts rappresenta il cuore pulsante del framework costituito dalle 4 funzioni principali :

  • init : viene invocato quando il componente viene caricato e non viene più eseguito fino a che non viene ricaricato. La funzione init può essere utilizzata per inizializzare la grafica del componete oppure per effettuare una chiamata verso il server se necessario. La funzione riceve i seguenti parametri: 

    context : consente l’accesso a tutte le proprietà e metodi resi disponibili dal framework. Inoltre espone i valori passati tramite le proprietà definite nel manifest file.
    notifyOutputChanged: allerta il framework della presenza di un nuovo output da inviare all’host.
    state: consente di conservare dati di sessione.
    container:utilizzato per attaccare gli elementi del DOM. 
  • updateView : processa ogni cambiamento proveniente dall’esterno in modo da far aggiornare il componente. Viene sempre invocato dopo init e risulta molto importante quando bisogna resettare il componente. 
  • getOutput: espone all’host i campi di output. Questa funzione invocata direttamente dal framework quando viene chiamata la funzione notifyOutputChanged(). 
  • destroy: utilizzato per applicare della logica quando il componente viene rimosso dal DOM.

Al fine di prendersi cura delle prestazioni risulta importante compredere come il framework richiama le funzioni descritte in precedenza e come esse interagiscono con l’host.

Qui di seguito riporto una rappresentazione, ricavata dalla documentazione di Microsoft, che schematizzare il ciclo di vita di un componente.

 

 
Questa rappresentazione potrebbe risultare un po ingarbugliata, pertanto nelle pagine seguenti ho preparato 3 esempi per cercare di semplificare il funzionamento del componente.

 

Esempio 1 – base

Per iniziare a vedere come il framework lavora ho semplicemente aggiunto dei log nel corpo delle funzioni, come riportato di seguito.

Eseguendo ora il componente in locale con il comando npm run start e aprendo la devtools del browser è possibile osservare che la prima funzione eseguita è init ma subito dopo viene eseguito anche update view.

Oltre a questo è possibile osservare che anche al solo cambiamento di una proprietà, come ad esempio altezza o larghezza del container del host, viene richiamata sempre la funzione update view.

Esempio 2 – Input 

Aggiungiamo un altro granello, vediamo come leggere il valore della proprietà passata in input e come il framework si comporta.

In questo caso nel corpo della funzione init viene salvato in una variabile globale il riferimento al container e successivamente aggiunto il valore string passato in input tramite la proprietà chiamata sampleProperty definita nel manifest.

Oltre alla funzione init è stata leggermente modificata anche la funzione updateView per rendere dinamico il cambiamento del valore in input.

Da questo semplice esempio si puo notare come ad ogni minimo cambiamento in input viene richiamata la funzione updateView e aggiornato il valore con il nuovo valore passato in input.

Esempio 3 – Password

Arricchiamo ora il codice per vedere il completo funzionamento.

Nella funzione init andiamo a salvare il riferimento alla funzione notifyOutputChaged tramite una variabile globale. Successivamente creiamo un nuovo elemento input aggiungendogli degli attributi di stile, un valore di default e un listener passando come callback la funzione onChangeInput.

La funzione onChangeInput si occuperà soltanto di invocare la funzione notifyOutputChanged per notificare al framework di un cambiamento e richiamare la funzione getOutputs.

La funzione getOutputs restituirà il valore dell input text tramite la proprietà definita nel xml chiamata in questo caso sampleProperty.

NOTA Se viene effettuato un cambiamento dalla UI ma la funzione notifyOutputChanged non viene invocata allora nemmeno la getOutputs non sarà chiamata e questo significa che il valore non sarà aggiornato.

Sviluppando un PCF devi essere consapevole del fatto che creando un controllo standard ne eseguiamo il rendering nel contenitore che viene fornito al componente.

Questo però in termini di performance non è ottimale in quanto le attività di aggiornamento del DOM potrebbero rallentare l’usabilità, meglio se sviluppiamo un controllo PCF che si basa su React.

In altre parole un controllo standard risiede in un HtmlDivElement e montato direttamente nel DOM del browser.

Anche React manipola il DOM ma in maniera diversa.

Invece di modificare direttamente il contenuto del DOM, React mantiene in memoria un modello del DOM chiamato virtual DOM e gli applica tutte le modifiche quando l’interfaccia cambia.

Questo modello del DOM contiene al suo interno tutti gli elementi dell’interfaccia rappresentati come normali oggetti JavaScript.

Tramite uno speciale algoritmo React calcola la differenza tra il DOM del browser e il suo modello. Di conseguenza nel DOM del browser verranno aggiornate solo le parti che risultano diverse tra i due modelli con un significativo guadagno dal punto di vista delle prestazioni.

Oltre a questo lo sviluppo di componenti custom con React introduce ulteriori benefici come ad esempio la possibilità di utilizzare gli hook di React.

Per creare un componente basato su React puoi usare il comando seguente:

pac pcf init -n ReactSample -ns SampleNamespace -t field -fw react

Una volta creato il progetto avrai di nuovo la stessa struttura con in più il componente React, di default viene creato HelloWorld.tsx

Puoi scrivere il tuo componente React sfruttando un approccio class component oppure functional component.

Oltre a questo possiamo beneficiare degli hook di React migliorando notevolmente il componente.

Inoltre, avendo pac aggiornato all’ultima versione, il PCF basato su React sarà creato di tipo virtual. Questo si osserva direttamente nel manifest.

Per un componente standard ogni controllo quando viene renderizzato istanzierà un suo virtual dom causando un overhead.

Se ad esempio hai 5 controlli ci saranno 5 virtual DOM.

Oltre a questo il bundle del componente che verrà caricato può avere versioni differenti rispetto ad altri componenti presenti nel host, causando così un eccessivo aumento nel consumo di memoria.

Con un cotrollo virtual questo approccio cambia notevolmente.

In questo scenario le librerie, compreso React, sono condivise tra i vari componenti. Inoltre il componete sarà agganciato direttamente al DOM del parent, introducendo così un significativo miglioramento delle performance.

Per distribuire il componente nell’ambiente dataverse è possibile scegliere tra due metodi.

È possibile usare il comando CLI in modo che una soluzione temporanea esegua rapidamente il push del componente per consentire il test. Questo metodo risulta idoneo durante lo sviluppo del componente.

L’altra opzione consiste nel creare una soluzione per il componente e importarla separatamente in Dataverse.

Questa opzione è utile per l’uso in pipeline o distribuzioni manuali in ambienti diversi dall’ambiente di sviluppo.

In questa guida affronteremo la prima soluzione, ovvero il deploy con Power Platform CLI

Come prima cosa è necessario definire un profilo di autenticazione per stabilire una connessione valida con l’ambiente Dataverse che si vuole utilizzare.

Power Apps CLI fornisce un comando per creare una profilo:

pac auth create –url <your Ddtaverse URL>

Tramite il comando pac auth list puoi vedere la lista completa delle connessioni create, il carattere * indica l’ambiente selezionato.

Per selezionare un ambiente puoi utilizzare il seguente comando :

pac auth select –index <index of the profile>

Ora che hai selezionato l’ambiente possiamo passare al porting della solution e per farlo puoi utilizzare il seguente comando:

pac pcf push –publisher-prefix <your publlisher prefix>

Quando si utilizza ” pcf push “, il controllo della versione viene saltato e il controllo creato dal codice sorgente viene importato al di sopra di ciò che è nell’organizzazione

Completato il rilascio del componente puoi andare direttamente nell’ambiente Dataverse e troverai la soluzione che hai appena rilasciato.

Infine non dimenticarti di aggiornare la versione del componente prima di rilasciarlo nell’ambiente altrimenti la modifica non verrà pubblicata.