Introduzione ai componenti javascript RD3
linkIntroduzione
Instant Developer, fin dalla sua origine, permette di personalizzare le applicazioni che vengono sviluppate. E' possibile personalizzare l'IDE ma anche personalizzare i template utilizzati dall'IDE per generare le applicazioni web. La personalizzazione della parte server, con l'aggiunta di classi C#/Java/Javascript è sempre stata più semplice di quella dell'interfaccia utente: aggiungere un nuovo componente grafico che non fosse già parte del template è complicato.
Nella versione 20.0 di Instant Developer abbiamo cercato di semplificare l'aggiunta di nuovi componenti client di terze parti. In particolare abbiamo cercato di semplificare l'integrazione con il framework già esistente permettendo di inserire oggetti grafici e integrarli con il framework di Instant Developer.
Vediamo di seguito come si integra un componente javascript.
Definizione dell'interfaccia nell'IDE
Per prima cosa occorre definire nel progetto una libreria che descriva come è fatto l'oggetto client. Questa nuova libreria è di tipo "libreria client" e si aggiunge tramite il relativo comando del menù contestuale del progetto.
Se il parametro è di tipo IDMap la controparte client sarà un Object. Se, invece, il parametro è di tipo IDArray sarà mappato con un array client.
Nota 1: Non è necessario indicare l'espressione in C# o Java: viene automaticamente calcolata da Instant Developer ogni volta che cambia il nome della funzione.
Nota 2: Non è possibile specificare altri tipi di oggetti perché devono essere serializzabili in JSON.
Nota 3: Non è possibile definire funzioni perché avvenendo in modo asincrono la comunicazione con il javascript non c'è modo di ottenere un valore in modo sincrono.
Utilizzo nei frame
Una volta definita la libreria client, che descrive come è fatto l'oggetto javascript corrispondente, è possibile indicare ad Instant Developer dove si usa.
Per farlo è sufficiente tirare la libreria all'interno dei riquadri delle videate o all'interno di campi statici (come un qualunque altro riquadro: pannelli, alberi, book, grafici, etc.).
Utilizzo nei campi in lista
Dalla versione 21.0 è possibile utilizzare componenti personalizzati anche nei campi di pannello in lista.
Per farlo basta tirare la libreria sul campo di pannello (quello con icona gialla) nell'albero oppure direttamente dall'anteprima della videata.
Nel designer non verrà mostrato nulla se non il nome della libreria client che è collegata al campo di pannello.
Per interagire con gli oggetti in lista occorre valorizzare le proprietà ed invocare i metodi nell'evento OnDynamicProperties, mentre per i campi fuori lista o in dettaglio si può farlo in qualunque altro punto del codice.
Classe wrapper lato client
Per facilitare l'inserimento di qualunque oggetto grafico occorre una classe di interfaccia scritta in Javascript. Questa classe è quella che si inserisce tra il framework di Instant Developer (RD3) e l'oggetto client di terze parti.
In fondo all'articolo è scaricabile un template di classe wrapper con tutto ciò che serve per partire.
Questa classe deve avere la stessa forma di quella della libreria client che abbiamo definito nel progetto. Deve avere le stesse proprietà e possedere gli stessi metodi che abbiamo definito nella libreria all'interno del progetto.
Tale file adrà inserito nella directory custom dell'applicazione in cui utilizziamo la libreria client. Nella directory custom dovranno essere inseriti anche tutti gli eventuali file utilizzati dall'oggetto client di terze parti: file javascript, font, css, etc.
Nella videata delle proprietà della libreria client occorre indicare il percorso del file Javascript di interfaccia. Vedremo più avanti come deve essere scritto il file.
Attenzione: se sono stati già personalizzati i file Desktop.htm e/o Desktop_sm.htm occorre riallinearli al template inserendo le nuove macro che sono state inserite e che vengono utilizzate da Instant Developer per inserire il file Javascript wrapper.
Vediamo ora come deve essere definita la classe wrapper scritta in javascript. Innanzitutto il nome della classe deve concidere con il nome del file. Se la classe si chiama MyClientLibrary il file si deve chiamare MyClientLibrary.js. Il nome del file, infatti, viene utilizzato da Instant Developer per creare, quando necessario, l'istanza della classe Javascript lato client.
La classe wrapper deve estendere la classe del framework CustomElement come mostrato nell'esempio seguente:
function MyClientLibrary(owner)
{
// Call base constructor
CustomElement.call(this, owner);
//
// Initialization of properties
}
//
// Define extension of class
MyClientLibrary.prototype = new CustomElement();
La classe base CustomElement definisce alcuni metodi che vengono automaticamente chiamati dal framework RD3 quando l'elemento viene creato (perché la videata viene aperta) e distrutto (perché la videata viene chiusa). Questi metodi vanno implementati nella propria classe. All'interno di questi metodi occorre creare l'oggetto client vero e proprio. Il codice da utilizzare dipende dall'oggetto che si occorre creare. Per questo occorre leggere la documentazione del componente grafico e scrivere il codice corrispondente.
Nel metodo Realize occorre creare gli oggetti DOM dell'oggetto client. E' possibile utilizzare il parametro parent per attaccare gli oggetti DOM a quelli già esistenti dell'applicazione.
Nel metodo Unrealize occorre distruggere (rimuovere dal DOM) gli oggetti inseriti nel metodo Realize.
MyClientLibrary.prototype.Realize = function (parent)
{
// Call base method
CustomElement.prototype.Realize.call(this, parent);
//
// Create the element
}
MyClientLibrary.prototype.Unrealize = function ()
{
// Call base method
CustomElement.prototype.Unrealize.call(this);
//
// Destroy the element
}
Le proprietà valorizzate lato server vengono automaticamente inviate al client. Per esempio se la libreria ha una proprietà chiamata center e, lato server, scriviamo
[sotto-videata].center = true
il sistema invierà quel valore al client appena verrà preparata la risposta da inviare al browser. Pertanto, lato client, la proprietà "this.center" sarà valorizzata al valore true. Se è necessario essere informati di quando il server cambia la proprietà (perché, per esempio, si desidera fare qualcosa sul componente quando cambia la proprietà) occorre definire un getter/setter della proprietà in questo modo:
Object.defineProperty(MyClientLibrary.prototype, "nomeProprietà", {
get: function () {
return ...;
},
set: function (value) {
...
}
});
Caricamento dipendenze
Per caricare i file dell'oggetto grafico (es: file javascript, file css) è possibile procedere in 2 modi:
- inserire i file nei file Desktop.htm e Desktop_sm.htm
- caricarli dinamicamente, quando la videata, contenente l'oggetto grafico, viene aperta la prima volta
CustomElement.LoadRequirements = function (urls, type, callback)
Il primo parametro indica quali risorse caricare. Può essere un URL (relativo o assoluto) o un array di URL (relativi o assoluti). Se viene fornito un array di URL il caricamento avviene seguendo l'ordine degli URL nell'array e in sequenza. L'array è da utilizzare se occorre caricare i file in un determinato ordine.
Il secondo parametro indica il tipo di risorsa da caricare: "JS" o "CSS".
Il terzo parametro è una funzione che viene chiamata dal sistema quando il caricamento è completo (callback).
Notifica eventi e modifiche a proprietà
Per notificare un evento al server occorre scrivere il seguente codice:
this.SendEvent("nomeEvento", [par1, par2, ...]);
Il primo parametro è il nome dell'evento senza spazi come definito nella libreria client del progetto. Il secondo parametro (opzionale se l'evento non ha parametri) è un array dove occorre inserirei valori dei vari parametri.
Se si desidera inviare il valore di una proprietà al server occorre chiamare il metodo SendProperty:
this.SendProperty("nomeProprietà", valoreProprietà);
Anche in questo caso il nome della proprietà deve essere quello indicato nella libreria client del progetto, tolti gli eventuali spazi. Il secondo parametro è il valore della proprietà. Se non viene specificato il sistema invia automaticamente il valore di this.nomeProprietà
.
Metodi per i frame
Quando il componente è utilizzato in un frame il framework invoca il metodo AdaptLayout() overridando il quale si può adattare l'oggetto DOM all'oggetto che lo contiene.
Metodi per campi in lista
Quando il componente è utilizzato in un campo di pannello il framework invoca una serie di metodi.
Per fare in modo che il componente si disegni/comporti come si desidera occorre overridare i metodi necessari (non è detto che serva overridarli tutti).
Questi sono i metodi che il framework invoca:
- GetDOMObj(): chiamato per avere l'oggetto DOM principale (da implementare obbligatoriamente).
- SetValue(value): chiamato quando cambia il valore del campo.
- GetValue(): chiamato per sapere il valore del campo.
- SetEnabled(enabled): chiamato quando cambia lo stato di abilitazione del campo.
- SetVisible(visible): chiamato quando cambia lo stato di visibilità del campo.
- SetActive(active): chiamato quando cambia lo stato di attivazione del campo.
- SetLeft(x): chiamato per impostare la posizione di sinistra.
- SetTop(y): chiamato per impostare la posizione in alto.
- SetWidth(w): chiamato per impostare la larghezza.
- SetHeight(y): chiamato per impostare l'altezza.
- SetVisualStyle(vs): chiamato quando cambia il visual style associato al campo.
- SetBackGroundImage(img): chiamato quando cambia l'imagine di sfondo del campo.
- HideContent(hide, disable): chiamato quando il contenuto del campo deve essere svuotato (ad esempio quando il pannello passa in QBE).
- UpdateCell(): chiamato al termine di ogni richiesta nel quale è possibile leggere tutte le proprietà del componente e aggiornare di conseguenza il DOM.
- CanHaveFocus(): chiamato per sapere se il campo può ricevere il fuoco.
- Focus(): chiamato quando il campo deve essere fuocato.
Ultima modifica: 28/11/2022 / Validità: da 20.0.7800