Creare e utilizzare controller personalizzati
Obiettivi di apprendimento
Al completamento di questa unità, sarai in grado di:
- Spiegare cos'è un controller personalizzato e descriverne gli attributi principali.
- Creare una classe controller personalizzati.
- Utilizzare un controller personalizzato in una pagina Visualforce.
Introduzione ai controller personalizzati
Per aggiungere un controller personalizzato a una pagina Visualforce, fai riferimento al nome della classe del controller nell'attributo controller
di <apex:page>
.
Quando la pagina utilizza un controller personalizzato, non è possibile utilizzare un controller standard. Le pagine utilizzano un attributo diverso per impostare il controller personalizzato.
- Apri la Developer Console e fai clic su File | New | Visualforce Page (File | Nuovo | Pagina Visualforce) per creare una nuova pagina Visualforce. Inserisci
ContactsListWithController
come nome della pagina.
- Nell'editor, sostituisci qualsiasi markup con il seguente.Quando proverai a salvare questa pagina, si verificherà un errore perché
<apex:page controller="ContactsListWithController"> <apex:form> <apex:pageBlock title="Contacts List" id="contacts_list"> <!-- Contacts List goes here --> </apex:pageBlock> </apex:form> </apex:page>
ContactsListWithController
non esiste ancora. Non preoccuparti, sarà la prossima cosa che sistemeremo.
Creare una classe Apex Controller personalizzato
Un controller personalizzato non è altro che una classe Apex scritta da te utilizzando la Developer Console.
Esistono molte classi di sistema e di utilità che aiutano a scrivere la logica dei controller personalizzati, ma l'unico requisito affinché una classe possa essere utilizzata come controller personalizzato è che esista.
- Apri la Developer Console e fai clic su File | New | Apex Class (File | Nuovo | Classe Apex) per creare una nuova classe Apex. Inserisci
ContactsListWithController
come nome della classe.
Nell'editor, sostituisci qualsiasi codice con il seguente.
public class ContactsListWithController { // Controller code goes here }
Come per le pagine Visualforce, è necessario salvare le modifiche in Apex quando lo si modifica. Non è chissà cosa e al momento non svolge alcuna funzione, però fa scomparire l'errore nella pagina Visualforce.
- Torna alla pagina Visualforce e salvala di nuovo. Il messaggio di errore dovrebbe essere scomparso e la pagina dovrebbe essere salvata correttamente.
- Fai clic su Preview (Anteprima) per aprire un'anteprima della pagina che potrai guardare mentre apporti le modifiche. Si apre una nuova finestra in cui sono visualizzati gli elementi standard dell'intestazione e della barra laterale della pagina di Salesforce, ma ancora nessun contenuto.
A prima vista, questi due nuovi elementi che hai creato non sembrano molto interessanti. Tuttavia, pur trattandosi al 90% di codice segnaposto, i due elementi – la pagina Visualforce e il controller Apex – sono collegati tra loro. Non appena aggiungerai dell'altro codice al controller, la pagina sarà in grado di utilizzarlo.
Oltre i concetti di base
Potresti aver notato che questa classe di controller personalizzati non eredita da un'altra classe, né implementa un'interfaccia che promette di conformarsi ai requisiti di un controller Visualforce. Neppure i controller più complessi fanno cose del genere, perché non esiste una classe da cui ereditare o un'interfaccia da implementare. Questo ti lascia libero di creare le classi e le interfacce che preferisci man mano che fai sempre più esperienza con Apex.
Aggiungere un metodo per recuperare i record
Crea un metodo getter per eseguire una query SOQL che restituisca i record che desideri visualizzare nella pagina.
Lo scopo principale della maggior parte dei controller è quello di recuperare i dati per la visualizzazione o di gestire gli aggiornamenti dei dati. In questo semplice controller, è sufficiente eseguire una query SOQL di base per trovare i record dei referenti e quindi rendere tali record disponibili alla pagina Visualforce.
- Nella classe
ContactsListWithController
, sostituisci la riga di commento// Controller code goes here
(Inserire qui il codice del controller) con il seguente codice.Questo codice aggiunge una variabile membro privata, una stringa denominataprivate String sortOrder = 'LastName'; public List<Contact> getContacts() { List<Contact> results = Database.query( 'SELECT Id, FirstName, LastName, Title, Email ' + 'FROM Contact ' + 'ORDER BY ' + sortOrder + ' ASC ' + 'LIMIT 10' ); return results; }
sortOrder
e un metodo pubblico,getContacts()
.sortOrder
è piuttosto facile da capire: è semplicemente il nome del campo in base al quale ordinare i referenti. AnchegetContacts()
è piuttosto semplice ma, se non hai mai visto Apex prima d'ora, potrebbe essere difficile da afferrare all'inizio. L'effetto del metodo è quello di eseguire una query SOQL per ottenere un elenco di record referenti e poi restituire tale elenco di referenti al chiamante del metodo. E chi sarà il chiamante? La pagina Visualforce, ovviamente.
- Nella pagina
ContactsListWithController
, sostituisci la riga di commento<!-- Contacts List goes here -->
(Inserire qui l'elenco dei referenti) con il seguente markup.Quando salvi questa pagina dovresti vedere una tabella dall'aspetto familiare con le informazioni sui referenti.<!-- Contacts List --> <apex:pageBlockTable value="{! contacts }" var="ct"> <apex:column value="{! ct.FirstName }"/> <apex:column value="{! ct.LastName }"/> <apex:column value="{! ct.Title }"/> <apex:column value="{! ct.Email }"/> </apex:pageBlockTable>
Il markup della pagina ContactsListWithController
dovrebbe avere un aspetto piuttosto familiare. A parte l'attributo controller
del tag <apex:page>
, è praticamente lo stesso codice che si usa per creare la pagina con il controller standard.
La differenza sta in ciò che accade quando l'espressione {!contacts }
viene valutata. In questa pagina, Visualforce traduce questa espressione in una chiamata al metodo getContacts()
del controller. Questo metodo restituisce un elenco di record referenti, che è esattamente ciò che si aspetta l'<apex:pageBlockTable>
.
Il metodo getContacts()
è definito metodo "getter" e rappresenta uno schema generale in base al quale {!someExpression }
nel markup Visualforce si connette automaticamente a un metodo denominato getSomeExpression()
nel controller. Per la pagina questo è il modo più semplice per accedere ai dati che deve visualizzare.
Aggiungere un nuovo metodo di azione
Per rispondere agli input utente nella pagina, occorre creare metodi di azione nel controller personalizzato.
Mostrare i dati è una cosa fantastica, ma rispondere alle azioni utente è essenziale per qualsiasi app web. Con un controller personalizzato, è possibile creare tutte le azioni personalizzate che si desiderano supportare in una pagina, scrivendo metodi di azione per rispondere all'attività utente.
- Nella classe
ContactsListWithController
, sotto al metodogetContacts()
, aggiungi i due metodi seguenti.Questi due metodi modificano il valore della variabile privatapublic void sortByLastName() { this.sortOrder = 'LastName'; } public void sortByFirstName() { this.sortOrder = 'FirstName'; }
sortOrder
.sortOrder
viene utilizzata nella query SOQL che recupera i referenti e la modifica disortOrder
cambierà l'ordinamento dei risultati.
- Nella pagina
ContactsListWithController
, sostituisci i due tag<apex:column>
perct.FirstName
ect.LastName
con il seguente markup.Anche se l'aspetto visivo rimane invariato, se adesso fai clic sulle intestazioni colonna First Name (Nome) e Last Name (Cognome), cambia l'ordinamento dell'elenco di referenti. Bel lavoro!<apex:column value="{! ct.FirstName }"> <apex:facet name="header"> <apex:commandLink action="{! sortByFirstName }" reRender="contacts_list">First Name </apex:commandLink> </apex:facet> </apex:column> <apex:column value="{! ct.LastName }"> <apex:facet name="header"> <apex:commandLink action="{! sortByLastName }" reRender="contacts_list">Last Name </apex:commandLink> </apex:facet> </apex:column>
Il nuovo markup aggiunge due componenti annidati a tutti i componenti <apex:column>
. <apex:column>
di per sé ha un'intestazione di testo normale, ma noi vogliamo rendere l'intestazione selezionabile. <apex:facet>
ci permette di impostare come vogliamo il contenuto dell'intestazione di colonna. Quello che vogliamo è un link che chiami il metodo di azione appropriato. Il collegamento viene creato utilizzando il componente <apex:commandLink>
, con l'attributo action
impostato su un'espressione che fa riferimento al metodo di azione del nostro controller. (Facciamo notare che i metodi di azione, a differenza dei metodi getter, hanno lo stesso nome dell'espressione che fa riferimento a loro.)
Facendo clic sul link, si attiva il metodo di azione nel controller. Il metodo di azione modifica la variabile privata dell'ordinamento, dopodiché la tabella viene visualizzata nuovamente. Quando la tabella viene visualizzata nuovamente, {!contacts }
viene valutato un'altra volta e la query viene ripetuta utilizzando ordinamento appena impostato. Il risultato finale è una tabella ordinata nuovamente in base all'ordine richiesto dal clic dell'utente.
Oltre i concetti di base
Il testo dell'intestazione per le colonne del nome e del cognome è hardcoded in questo markup. Ma cosa succede se non tutti gli utenti utilizzano l'inglese? L'interfaccia utente standard di Salesforce contiene versioni tradotte dei nomi campo per tutti gli oggetti standard e tu stesso puoi fornire una traduzione per gli oggetti personalizzati. Come puoi accedervi? Invece del testo normale, prova a utilizzare questo markup: <apex:outputText value="{!$ObjectType.Contact.Fields.FirstName.Label }"/>
. Questo è il modo giusto per fare riferimento all'etichetta di un campo, anche se l'organizzazione utilizza la stessa lingua, perché si aggiornerà automaticamente se il nome campo viene modificato.
Ulteriori informazioni...
I controller personalizzati e il linguaggio Apex consentono di fare praticamente tutto ciò che si vuole nelle pagine Visualforce.
I metodi getter estraggono i dati dal controller e li trasferiscono alla pagina. Esistono metodi setter corrispondenti che permettono di inviare i valori dalla pagina al controller. Come nel caso dei metodi getter, i setter devono essere preceduti dal prefisso "set". A parte questo, sono solo metodi che accettano un argomento.
Un'alternativa ai getter e setter è l'utilizzo delle proprietà Apex. Le proprietà sono una specie di combinazione di una variabile con metodi getter e setter, con una sintassi che li raggruppa in modo più chiaro. La dichiarazione di una semplice proprietà che fa riferimento a un oggetto personalizzato potrebbe presentarsi in questo modo.
public MyObject__c myVariable { get; set; }
Le proprietà possono essere pubbliche o private e possono essere di sola lettura o anche di sola scrittura, omettendo il get o il set. Inoltre, è possibile creare implementazioni per i metodi get o set, quando si desidera eseguire una logica aggiuntiva oltre al semplice salvataggio e recupero di un valore.
Le proprietà sono una funzione generale di Apex, non specifica di Visualforce. Apex è un linguaggio di programmazione completo e, oltre a essere il partner naturale per la creazione di pagine Visualforce complesse, viene utilizzato in molti altri contesti di sviluppo di Lightning Platform. Per conoscere i numerosi modi per imparare a usare Apex in modo completo, consulta gli argomenti dedicati ad Apex, qui e nelle risorse riportate in fondo a questa pagina.
Il ciclo di vita di una richiesta e di una risposta di Visualforce può sembrare complesso, in un primo momento. In particolare, è importante capire che non esiste un ordine specifico in cui vengono chiamati i getter o i setter (o le proprietà, se utilizzate), quindi non bisogna introdurre dipendenze dall'ordine di esecuzione tra di loro. La Guida per gli sviluppatori Visualforce contiene molti altri dettagli nelle sezioni pertinenti, in particolare nel capitolo Custom Controllers and Controller Extensions (Controller personalizzati ed estensioni dei controller).
Risorse
- Visualforce Developer Guide: Creating Your First Custom Controller (Creare il primo controller personalizzato)
- Visualforce Developer Guide: Custom Controllers and Controller Extensions (Controller personalizzati ed estensioni dei controller)
- Apex Developer Guide
- Blog degli sviluppatori Salesforce: Apex Template: Visualforce Controller (Modello Apex: controller Visualforce)
- Blog degli sviluppatori Salesforce: A Real Controller for Visualforce Charting (Un vero controller per grafici Visualforce)
- Visualforce Developer Guide: apex:outputLink Component (Componente apex:outputLink)
- Visualforce Developer Guide: apex:repeat Component (Componente apex:repeat)