1 Manuale Servoy per Principianti di Servoy Training & Consulting San Francisco, CA, USA Website: www.mcgilly.com E-mail: [email protected] v 1.1 Copyright 2006, All Rights Reserved Questo manuale viene fornito gratuitamente. Se esso vi risultasse di aiuto nell’apprendimento di Servoy e voleste contribuire per i costi sostenuti, prego spedire il vostro contributo tramite PayPal a [email protected]. Gli aggiornamenti saranno effettuati regolarmente – controllate spesso! Table of Contents Introduzione ................................................................................................................. Come Imparare Servoy .............................................................................................. Risorse Disponibili .................................................................................................... Suggerimento sul percorso da imparare ................................................................... Ottenere informazioni dal Forum di Servoy ............................................................ Devo conoscere l’ SQL per usare Servoy? .............................................................. La Architettura di Servoy ............................................................................................ Connessione al database SQL Anywhere ................................................................ SQL Anywhere ........................................................................................................ 15 Connessione al Repository ..................................................................................... 15 Problemi sulla Connessione a SQL Anywhere: ............................................... 17 Creazione e Connessione a un Nuovo Database ................................................... 19 Come posso guardare i dati ?...................................................................................... 2 Dove sono memorizzati i miei schemi di database? In Servoy o DBMS? ............. Tabelle e Colonne ........................................................................................................ Sequenze ...................................................................................................................... Tutto ciò che Volete Conoscere sui Foundsets .......................................................... Che cos’è un foundset? ....................................................................................... Come funzionano i foundsets? ............................................................................ Come programmare la navigazione in un foundset ................................................... Funzioni Foundset e Funzioni Controller ................................................................ Looping Attraverso un Grande Foundset ................................................................... Come Aggiunte Modifiche & Cancellazioni influenzano i Foundsets ............... Contenitori: Vista di Variabili, Dataproviders, Calcoli e Elementi ...................... Dataproviders............................................................................................................... Come si assegnano i dataproviders nelle form & metodi ......................................... Assegnare un Dataproviders a i Records Correlati .................................................... Elementi ....................................................................................................................... Molti Controllers Meno Tempo .................................................................................. Oggetto Controller ....................................................................................................... Oggetto currentcontroller ............................................................................................ Controller Form ........................................................................................................... Come & Quando il Salvataggio ai Dati Modificati .................................................. Panoramica sui Salvataggi in Servoy ......................................................................... Uso del setFocusLostSaveEnabled(false) ............................................................... Uso di Transactions .................................................................................................... Cambiamenti in Servoy 3.x ....................................................................................... Convalida del Record Prima di Salvare .................................................................... Panoramica sulla Convalida Dati ............................................................................... Tre differenti approcci ................................................................................................ Funzione setFocusLostSaveEnabled() ....................................................................... Comportamento di Modifiche e Salvataggio Prima del 3.x ..................................... Verifica Univocità di un Record.................................................................................. Approccio #1 – scrivere generica funzione checkUniqueness() con SQL .......... Approccio #2 – uso di una relazione per test di uniqueness ................................ Approccio #3 – uso di foundset separato per ricercare matching record ........... Come Trovare le Date ................................................................................................ Panoramica sulle Date in Servoy................................................................................ La ricerca delle date per gli utenti.............................................................................. Programmare la ricerca delle date in un metodo ....................................................... 3 Date con la componente tempo .................................................................................. Consiglio: Uso di campi DATE invece di campi DATETI ME................................ Spiegazione dei Tabpanels .......................................................................................... Panoramica sui Tabpanels .......................................................................................... Related Tabpanels ....................................................................................................... Relationless Tabpanels ................................................................................................ Tabless Tabpanels ....................................................................................................... Come si Programmano i Tabs .................................................................................... Aggiunta/cancellazione di form a/da un tabpanel esistente ...................................... Le Relazioni ................................................................................................................... Panoramica sulle Relazioni ....................................................................................... Chiavi Primarie & Chiavi Esterne ............................................................................ Origine & Destinazione: Un Modo di Pensare alle Relazioni in Servoy ............ Relazioni Uno-a-Molti ................................................................................................ Relazioni Molti-a-Uno ................................................................................................ Relazioni Molti-a-Molti .............................................................................................. Relazioni nominate da voi .......................................................................................... Relazioni Globali......................................................................................................... Relazioni Nidificate .................................................................................................... Lettura, aggiunta & cancellazione di record correlati ............................................... Riassumendo le Relazioni ........................................................................................... Opzioni di Relazione ................................................................................................... Consigli e Convenzioni sulla Programmazione ........................................................ Stabilire convenzioni sui nomi e attenersi ad esse .................................................... Cliccare non scrivere! ................................................................................................ Usare application.output() per vedere 'ciò che sta girando' ...................................... Dichiarazione di vars globali nella finestra dataproviders .................................... Usare Ctrl-spacebar per velocizzare la codifica ..................................................... Essere consapevoli del case-sensitivity ................................................................ Settaggio delle proprietà a tempo di esecuzione ....................................................... Usare calcoli non -memorizzati per checkboxes ........................................................ Contenitori che non persistono alla uscita da modalità run -time ...................... Fare spesso il Back up delle soluzioni ................................................................... Uso dell’help .............................................................................................................. Global find & replace per correggere dopo la rinomina di un oggetto ................ Tasti chiave per andare in Servoy Editor ................................................................ 4 Non dimenticare il doppio == nel comando if! ...................................................... Selezionare righe di codice & formattarle tutte in un colpo ................................ In Editor non usare alcune keywords nei commenti (es.“function”) ................... I Colori a volte sono strani ........................................................................................ Debugger Consigli e Suggerimenti ............................................................................. Appendice ....................................................................................................................... Creazione di unaTabella con 500 record ................................................................... Introduzione Servoy è un brillante ambiente di sviluppo che incrementa la produttività dello sviluppatore. Riunisce diversi e potenti standard tecnologici (Java, JavaScript, JDBC, RMI, Database SQL, browser, CSS, XML ecc.) così da rendere più elegante ed efficiente l’intero prodotto. Lo Sviluppatore con il prodotto Servoy viene arricchito delle sue prerogative. Il mio nome è Adrian McGilly e sono un consulente e istruttore di Servoy, e membro della Servoy Alliance Network (SAN). Ho una laurea in Scienza della Informatica e Matematica e ho imparato Servoy nel 2006 dopo una dec ina di applicazioni sviluppate, usando principalmente Omnis e i database SQL. Fornisco sviluppo di applicazioni in Servoy e training a ciascun cliente. Per informazioni circa corsi di addestramento imminenti e altri servizi per favore fare riferimento al mio website. I miei corsi di addestramento sono elencati anche sotto gli Eventi Servoy Website. Per l’esperienza che maturata, insegno l’ambiente Servoy ai nuovi sviluppatori e leggendo le domande che vengono poste quotidianamente sul Forum di Servoy, mi sono accorto che c'erano dei temi che la documentazione di Servoy esistente non spiegava in 5 modo esaustivo, e ho deciso di fare qualche cosa in merito. Questo manuale è una raccolta dei ‘come-si fà’ con lezioni e discussioni per gli sviluppatori che intendono imparare Servoy. Esso non sostituisce la documentazione Servoy ma la completa, è un aiuto in modo da ottenere una comprensione più rapida . Potete spedirmi email per qualsiasi argomento all’indirizzo [email protected] con domande, commenti, critic he o correzioni che riguardino qualsiasi aspetto del manuale. Tutto il contenuto menzionato in questo manuale risulta applicato a Servoy v. 2.2.5. I miei ringraziamenti vanno a John Allen, Marc Norman, Jan Aleman e Bob Cusick per tutti i contributi di idee, correzioni, incoraggiamenti offerti per la creazione di questo manuale. Un grande grazie a tutti gli utenti Servoy che con domande e risposte sul Forum di Servoy mi hanno aiutato a identificare i temi da includere in questo manuale. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 6 Come Imparare Servoy by Adrian McGilly Risorse Disponibili Ci sono molte risorse disponibili per conoscere e usare Servoy. Di seguito un elenco di tutto ciò che serve per questo: • Documentazione di Servoy, disponibile per downl oad gratis formato PDF da PDF Documentation page del sito web di Servoy o per acquisto in formato libro dal Servoy Store. Comprende: Servoy Developer User's Guide Servoy Developer Reference Guide Advanced Programming Guide for Filemaker Developers Servoy Server Administrator's Guide • Servoy Magazine, un periodico online conversazionale pieno di molti consigli, tecniche e come -fare. • Online Tutorials sul sito web Servoy • Servoy Gallery – una sezione del sito web di Servoy che mostra schermate e spiegazioni su una dozzina le soluzioni Servoy già in produzione. Guardare a queste schermate è un modo valido per vedere le complete capacità GUI di Servoy. • Demo solutions soluzioni demo che potete scaricare dal website di Servoy, da esplorare e usare come maschere di esempio per le vostre soluzioni. • Questo manuale (Servoy Beginner's Handbook di Adrian McGilly). [TOP] 7 • The Servoy Forum – un gruppo di discussione online dove circa 1000 sviluppatori fanno domande, condividono e ottengono risposte. Il Personale degli sviluppatori di Servo y rispondono regolarmente alle domande su questo forum. • E per finire il più importante tool di apprendimento di tutti: Servoy stesso. Giocate. Pasticciate. Non dovete preoccuparvi–non vi morde. Il migliore modo per imparare è fare esperienza. Suggerimento sul percorso da imparare Questo è il mio suggerimento del percorso per conoscere Servoy. 1. Caricare l’ambiente Servoy e lanciarlo sul proprio computer usando il Sybase SQL Anywhere come database. Se avete problemi di connessione al database Sybase SQL Anywhere leggere la sezione sulla connessione al database. 2. Leggere la Developer User's Guide . È BENE saltare le parti che non si sentono molto attinent i alle proprie particolari necessità ma per voi sarebbe utile spendere del tempo per ogni sezione di questo libro in modo da capire le complete capacità di Servoy. Dovrete anche stare molto tempo sulle cose più difficili in Servoy. 3. Leggete la Developer Reference Guide , ma non cercate di capire tutto subito. Capirete col tempo. 4. Aprite la soluzione Demo svyCRM che è fornita insieme alla installazione Servoy e disponibile anche col download dalle Download Demo Solutions in Servoy Website. Guardate la soluzione, sia in esecuzione che in modalità di design. Guardate a come le form funzionano insieme. Guardate ai metodi presenti. Esplorate la finestra del dataproviders. Non dovete preoccuparvi di rovinare la soluzione demo – potrete in ogni momento reinstallarla . 8 5. Se non conoscete JavaScript, guardate il capitolo JavaScript Primer in Servoy Advanced Programming Guide for FileMaker Developers . Non avete bisogno di conoscere molto di JavaScript per cominciare in Servoy, bastano poche basi elementari - (grammatica, sintassi, dichiarazione di variabili & controllo del flusso). 6. Se non conoscete l’ SQL, date un’occhiata a SQL primer in Servoy Advanced Programming Guide for FileMaker Developers. Secondo la complessità del vostro progetto, potete anche non avere bisogno di usare SQL, ma è una buona cosa avere una comprensione di base e di come viene usato. 7. Evidentemente, se siete Sviluppatori di FileMaker, troverete che altre parti del Servoy Advanced Programming Guide for FileMaker Developers sono molto utili. 8. Probabilmente avete in mente un progetto che volete produrre con l’ausilio di Servoy. Dovete pensare di suddividerlo in parti semplici - per esempio, una form per poter registrare e scorrere i records del Cliente , e cominciate a costruirlo. Quando andrete a sbattere contro certi ostacoli, la speranza è quella di trovare risposta in questo manuale a molte delle vostre domande. Altrimenti, cercate in Servoy Magazine per vedere se qualche articolo è stato scritto sul tema, poi controllare anche il Forum di Servoy. La prossima sezione spiega come ottenere risposte dal Forum. 9. Per lo stesso motivo ricordate di dar e uno sguardo a Servoy Server Administrator's Guide. Potete capire Servoy se ne capite le capacità di a mministrazione di sistema. Ottenere informazioni dal Forum Servoy Probabilmente ogni domanda che un nuovo arrivato avesse quando comincia con Servoy la trova già nelle risposte sul Servoy Forum. Il trucco sta nel trovare il percorso che contiene domanda e risposta. 9 Otterrete ulteriore successo se trovate la risposta adatta per voi. Prendetevi un pò di tempo per capire il motore di ricerca del forum, come evidenziato sotto. La opzione “ricerca per tutti i termini” in particolare può aiutarVi a restringere la vostra ricerca. Devo conoscere l’ SQL per usare Servoy? La risposta è ‘sì e no’. È utile sapere un poco di SQL, ma in molti casi non è necessario, e certamente non quando siete principianti. Servoy vi permette di interrogare il vostro db con l’ SQL invece di usare i comandi standard find()/search(). Si può passare una query SQL a una funzione con databaseManager.getDataSetByQuery() per recuperare righe (records) di un dataset. Quindi potete scorrerne i dati, stamparne i reports, caricare questi dati in un foundset e mostrarli su una form, esattamente come se aveste fatto una ricerca 10 con Find() /search(). Questa è una scelta conveniente per quelli che conoscono le query SQL, ma spesso potete ottenere le stesse cose anche senza. Ci sono cose che si possono fare in una query SQL e che invece non si possono fare usando i comandi find()/search(). Un esempio sono gli outer joins, usati per reporting (visualizzazioni e stampe) di tabelle correlate fra loro quando di ogni tabella possono essere omessi alcuni suoi records. L’SQL può anche essere utile per recuperare i risultati dal vostro db senza perdere il foundset, come dimostrato nella sezione verifica della univocità di un record prima di salvarlo. Con database complessi, consultare direttamente il database con l’SQL spesso migliorerà significativamente l e performance delle nostre queries. Potete anche usare il plugin del rawSQL per modificare i dati del vostro database coi comandi SQL update, insert e delete, ma solamente per utenti di Servoy competenti che li conoscono. Raramente è necessario fare questo. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 11 12 La Architettura di Servoy by Adrian McGilly È importante capire l'architettura di Servoy. Segue una vista (fornitami da Servoy) Le applicazioni scritte con Servoy sono chiamate soluzioni. La prima cosa da capire è che la vostra soluzione e i v ostri dati sono due cose separate (come lo debbono essere!). I dati risiedono in un (o più) database SQL gestito da un (o più) server di database. La vostra soluzione risiede in un database SQL chiam ato [TOP] 13 Repository. Uno dei grandi meriti di Servoy è quello di gestire la memorizzazione della intera soluzione compreso le vostre GUI e tutta la codifica, in un database SQL standard, con JDBC conforme. Quando viene startato Servoy Developer, per default si aspetta di trovare un database server chiamato repository_server, e il relativo database chiamato servoy_repository. Qui è dove vengono immagazzinate le vostre soluzioni. Quando costruite una soluzione e fate modifiche ai disegni delle form e agli script (i metodi) che li sotten dono, Servoy in quel momento sta salvando il disegno della vostra form nel database servoy_repository. Quando lanciate una soluzione e aprite una nuova form, Servoy legge la form e tutti i metodi (legati alla form stessa) e tutti gli attributi direttamente dal servoy_repository. Al momento di popolare la form con i dati, Servoy legge i dati da qualsiasi database (o dai database) aziendale . I dati aziendali gestiti in una soluzione possono risiedere in più database e di più fornitori diversi. Mentre il repository è sempre contenuto in uno stesso database. La parte di Servoy con la quale gli utenti interagiscono direttamente è il Servoy Client, una applicazione Java che gira sul Java Virtual Machine disponibile gratis da Sun. La parte che gestisce tutto l’insieme è il Servoy Server che è scritto in Java e gira sul Tomcat application server. La applicazione server risiede tra le postazioni client di Servoy e i database(s), gestisce una varietà e un numero stupefacente di richieste dai Client di Servoy, e tutto mentre legge la intera soluzione e i dati del cliente dai database SQL. Il Java Client (a volte chiamato Smart Client-intelligente) è una applicazione Java che gira su Java Virtual Machine di ogni postazione client e fornisce agli utenti una “ricca esperienza UI”. Con la versione 3.x, Servoy presen ta un altro tipo di client - il Web Client. Con il Web Client gli utenti accedono alle soluzioni Servoy con un web browser. Il Servoy Server configura le forms usando 14 HTML, JavaScript, AJAX e gli altri protocolli browser standard, completi di bottoni, campi e liste popolate con dati, ecc. e li serve sul browser. Per alcune limitazioni tecnologiche dei browser, ci sono alcune caratteristiche UI che sono disponibili al Smart Client ma non disponibili al Web Client. Dedic herò una sezione al Web Client in una futura revisione di qu esto manuale. In aggiunta a queste componenti dell'architettura, i Java beans e i Servoy Plugins possono essere usati per estendere la funzionalità di Servoy. Queste componenti risiedono nelle cartelle sul Servoy Server (Non sulla postazione cliente) e vengono richiamati ogni qualvolta la soluzione li richiede. Le funzionalità di Servoy possono essere ulteriormente estese con le Elaborazioni Batch . Queste sono Soluzioni Servoy inserite in cartelle speciali sulla macchina server e la loro esecuzione può essere schedulata dalla Console Administration di Servoy Server. Quando usate l’ambiente di Sviluppo Servoy, è come se steste facendo girare una speciale postazione Client di Servoy su di una mini-versione di Servoy Server. In questo manuale viene usato il database Sybase ASA che viene fornito insieme a Servoy, ma la maggior parte del contenuto riferito al database si applica a tutti i database con driver JDBC-conforme di diversi fornitori. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 15 Connessione al database SQL Anywhere by Adrian McGilly SQL Anywhere SQL Anywhere è solo uno dei molti dbs al quale Servoy può connettersi, ma è l'unico che è fornito con l’ambiente Servoy, e che presumiamo di usare in questo manuale. SQL Anywhere ha diversi nomi. A volte viene chiamato ASA che sta per Adaptive Server Anywhere, e d è venduto da una filiale di Sybase chiamato iAnywhere. Prima di andare troppo avanti, voi dovreste scaricare una copia del tool di gestione del database, chiamato “SQL Anywhere Developer Edition” il cui componente principale è chiamato Sybase Central. Sybase Central vi permette di gestire i vostri schemi di database, (i tracciati di ogni tabella) con gli attributi di ogni colonna come NOT NULL, INDEXED and UNIQUE, scorrerne le righe (records) dei vostri dati, scriverne le query SQL, creare nuovi database, ecc. Per leggere su SQL Anywhere, visitare questo link: http://www.ianywhere.com/datasheets/sqla ny_9.html Per scaricare una copia gratuita di SQL Anywhere, visitare la pagina Download Sybase Central sul sito web di Servoy oppure andare a: http://www.ianywhere.com/downloads/ e cliccare su SQL Anywhere Developer Edition Connessione al Repository Per lanciare Servoy occorre essere abilitati alla connessione col database servoy_repository. Quando si apre Servoy, viene presentato un elenco di soluzioni nel repository e vi si chiede a quale volete collegarvi. [TOP] 16 Quando scegliete una di quelle soluzioni, il sistema cercherà di connettersi al database repository che le contiene tutte, e se non può trovarlo, voi otterrete un errore. Ci sono alcuni dettagli da precisare affinchè Servoy si possa connettere con successo al database Anywhere . Generalmente, dopo avere installato Servoy voi dovreste connettervi senza problemi, ma in passato ci sono state installazioni con problemi, così qui di seguito vengono proposti alcuni consigli in merito . Quando viene lanciato, Servoy attiva il motore del database SQL Anywhere che è contenuto principalmente ne l file dbsvr9.exe (dbsrv9 su Mac) nella cartella Sybase_db. SQL Anywhere guarda poi nel file sybase.config un elenco di database che si aspetta di trovare e quindi tenta di aprire ogni database presente nell'elenco. IMPORTANTE: voi potete vedere se SQL Anywhere è in funzione quando la sua icona appare nella barra del desktop (su Windows) o Activity Monitor nella cartella di Applications/Utilities su Mac. Se SQL Anywhere non parte, Servoy attiverà il seguente messaggio “non ci si può connettere al repository server specificato nelle preferenze”. Ogni qualvolta ottenete quest o messaggio, uscite da Servoy, aprite il file sybase_log.txt nella cartella sybase_db e andare alla fine. Di solito vedrete a fine file un messaggio che vi spiega il motivo dell’errore , del tipo “non si può aprire/leggere il seguente file: database/mydatabase.db.” Nota: è OK quando nella cartella “database” vengono trovati i database specificati nel file sybase.config. Non è OK quando nella cartella “database” non ci sono i database specificati nel file sybase. L'altra parte che ha bisogno di essere messa a posto è il settaggio della connessione a ogni database che Servoy deve usare. Queste connessioni al database sono chiamate semplicemente “servers”, e sono elencate nel Menu Modifica>>Preferenze sul tab DB Servers . Per fare in modo che Servoy si connetta a un database occorre avere definito un server in questo elenco. Per dettagli sul come si 17 creano questi server database andare al Servoy Developer User’s Guide. Prestare attenzione al fatto che se adesempio il vostro database è crm.db, allora dovete inserire ‘crm’ (senza apici) come nome del database (non ‘crm.db’). Problemi sulla connessione a SQL Anywhere: Corruzione o non sincronizzazione del .log e database Ciascun database ha un file .log con lo stesso nome (es. il file log di crm.db è il crm.log). Può accadere che il file di log non sia più sincronizzato con l'archivio del db. In questo caso, potete provare a cancellare l'archivio di log e SQL Anywhere ne creerà uno nuovo alla successiva prima apertura del database. Se non funziona, potete costringere Sybase a startare il database senza un archivio di .log usando la scelta '-f '. 1. In Windows, la procedura è: 2. Chiudere Servoy e chiudere ogni server Sybase. 3. Lanciare la applicazione dbsrv9.exe presente nella cartella Servoy\sybase_db 4. La applicazione vi permette di specificare i l nome database .db che dovete aprire, quindi inserite il carattere -f nel campo delle opzioni 5. Premete OK. Su Mac, la procedura è: Aprite una nuova finestra con /Applications/Terminal e inserire questi comandi (supponiamo che la vostra directory Servoy è localizzata in /Applications/Servoy): 18 cd /Applications/Servoy/database export DYLD_LIBRARY_PATH=/Applications/Servoy/syba se_db export PATH=$PATH:/Applications/Servoy/sybase_db dbsrv9 -f servoy_repository.db Versioni Discordanti di SQL Anywhere Ho visto accadere un errore riportato nel file sybase_log.txt, qualcosa come “manca capacità 32 ” o “manca capacità 35”. Questo di solito ha a che fare con versioni discordanti tra il database e il motore del database SQL Anywhere . Ciò non dovrebbe mai accadere con una installazione nuova , ma può accadere più avanti quando per esempio aprite un db con Sybase Central usando una versione più recente d el motore database dbsrv9.exe di quello usato nelle cartelle di Servoy. Se accade questo, basta portare la applicazione (dbsrv9.exe ) di Sybase in quella presente nella cartella di Servoy e questo dovrebbe risolvere il disallineamento. Firewalls I Firewalls possono interferire con Servoy nella connessione ai database SQL Anywhere. Se avete problemi di connessione, allora vi potrà essere di aiuto se potete chiudere il vostro firewall. Se state usando un firewall, cercate ne lla vostra configurazione del firewall tutte le regole che bloccano l’accesso al/dal dbsrv9.exe e rimuovete queste regole. Corruzione del Database Se qualcuno dei dbs elencati in sybase.config si è corrotto vi 19 potrebbe causare problemi. voi potete tentare di correggere la corruzione del database lanciando l’applicazione dbsrv9.exe con il parametro –f e a “force” il database. Aver bisogno di rilanciare SQL Anywhere e Servoy Se voi cambiate qualcosa in sybase.config, le modifiche avranno effetto solo la volta successiva che SQL Anywhere viene lanciato. Se SQL Anywhere sta già girando e voi aprite Servoy, i vostri cambiamenti a sybase.config saranno ignorati. Così dopo avere fatto i cambiamenti a questo archivio, assicuratevi di uscire da SQL Anywhere prima di lanciare Servoy. Per chiudere SQL Anywhere in Windows, dovete trovate la relativa icona nella barra in basso , poi click col tasto destro sull’icona e selezionate exit (o su Mac, scegliere ‘Quit’ dopo avere selezionato ‘dbsrv9 ' usando Activity Monitor?. Egualmente, se pensate di aver predisposto tutto bene ma Servoy si rifiuta ancora di connettersi, allora dovete sempre chiudere sia Servoy che SQL Anywhere, e poi rilanciare – Servoy usa un approccio tipo “caricamento pigro” al suo lancio e questo significa che alcuni cambiamenti non avranno effetto finché Servoy non viene rilanciato. Creazione e Connessione a un Nuovo Database Quando Servoy si è connesso con successo a SQL Anywhere, voi vorrete creare una soluzione nuova e iniziare a giocarci. Che database usereste? Voi potete usare uno dei database di esempio esistenti che vengono installati insieme a Servoy (sono inclusi example_data.db, user_data.db, crm.db e udm.db) oppure potete creare un database nuovo. In questo momento non siete ancora in grado di creare un db nuovo 20 in Servoy. Per farlo avete bisogno delle seguenti cose: 1. Uscire da Servoy 2. Chiudere il server SQL Anywhere usato da Servoy. Per chiudere SQL Anywhere in Windows, potete trovate la sua icona nella barra sul desktop, fare un click e scegliere exit (o su Mac, scegliere ‘Quit’ dopo avere selezionato ‘dbsrv9 ' usando l’Activity Monitor?. 3. Aprire Sybase Central e crea re un nuovo db e salvarlo nella cartella servoy\database. I dettagli su questa operazione si trovano in Servoy Developer User’s Guide ma la cosa più importante è di NON connettersi al nuovo db creato finché non avete completato i passi seguenti. 4. Aggiungete il vostro database nuovo nel file sybase.config della cartella sybase_db della vostra directory Servoy. 5. Avviare Servoy. Se Servoy apre con successo SQL Anywhere e si connette al repository, allora vi verrà presentato un elenco di soluzioni disponibili. Uscite premendo Annull e andate alle Preferenze sul tab DB Servers per aggiungere la connessione al vostro nuovo database. Per default lo username e la password per il vostro nuovo database SQL Anywhere è: username=dba password=sql. Servoy vi salverà questa nuova connessione, solo se la connessione al server database avrà successo. Nell'elenco dei server di database in Preferences>>DB Servers, ci sarà un X rossa vicino a ogni server sul quale non è riuscita la connessione al database corrispondente . 21 Come posso guardare i dati? Potete usare Sybase Central per guardare gli schemi e i dati di ogni tatabella cliente. Quando vi connettete a un db con Sybase Central potete andare su ogni tabella dati, selezionate il tab ‘data’ e visualizzate le righe e le colonne dei vostri dati. Sappiate che se fate delle modifiche ai dati in ambiente Servoy, per poterli vedere in Sybase Central dovete fare un refresh oppure chiudere e riaprire . C'è anche un editor di Query SQL conversazionale in Sybase Central che vi può essere utile (sebbene non è difficile costruire un tool simile in Servoy - c'è n’è uno già costruito nella soluzione demo svyCRM, che si chiama AdHoc Query sotto il tab Admin). by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 22 Dove sono memorizzati i miei schemi di database? In Servoy o in DBMS? by Adrian McGilly Tabelle e colonne Servoy permette di gestire alcune cose sul database all’interno del suo ambiente. Potete creare e cancellare ta belle di database, creare colonne, e le sequenze di tabella. Per qualsiasi altro tipo di modifiche allo schema (es. modificare l’attributo, rinominare o cancellare una colonna , rinominare una tabella ecc.) avrete assolutamente bisogno di usare Sybase Central. Quando una soluzione Servoy viene aperta, carica lo schema del db. Se voi andate in Sybase Central e modificate lo schema del db (es. aggiungete una colonna, cambiate gli attributi di una colonna, aggiungete una nuova tabella) vedrete i cambiamenti nella finestra del dataprovider di Servoy la volta successiva che avviate Servoy. (È meglio chiudere SQL Anywhere e rilanciare Servoy dopo avere fatto le modifiche, sebbene in alcuni casi non sia proprio necessario.) Voi dovete prestare attenzione quando fate questo, così come modificare qualsiasi indice assegnato alle tabelle e alle colonne. Alcuni esempi: [TOP] 23 Modifiche al backend DB Effetti in Servoy Rinominare una colonna Il nome nuovo apparirà nella finestra di Dataproviders la volta successiva che avviate Servoy ma il campo assegnato a quella colonna su qualsiasi form sarà mostrato vuoto–poichè contiene il vecchio nome–e tutti i metodi che usano quel vecchio nome causer anno un errore. Cancellare una colonna I cambiamenti appariranno nella finestra Dataproviders la volta successiva che avviate Servoy; qualsiasi campo assegnato alla colonna cancellata sarà mostrato vuoto; i metodi che usano quella colonna causeranno un errore. Modificare attributi di colonne I cambiamenti saranno riflessi nella finestra Dataproviders alla successiva apertura di Servoy; invece il funzionamento dei campi che mostrano quella colonna e dei metodi che usano quella colonna può essere possibile ma ciò dipende dal tipo di modifiche apportate. Cancellare o rinominare una tabella Se cancellate o rinominate una tabella che è usata in una soluzione, otterrete un errore , sia allo startup della vostra soluzione che anche la prima volta che la soluzione usa la tabella. 24 Notare che c'è un comando global find & replace in Servoy Editor che vi permette di fare cambiamenti globali ai vostri metodi JavaScript. Non ci sono però comandi find/replace che agiscono sui settaggi nel pannello delle proprietà. Sequenze Voi potete definire le sequenze in Servoy. Un inserimento di sequenza, chiamato “Servoy Sequence” permette a Servoy di gestire la generazione di una sequenza numerica (diversa dalla “sequenza database” dove si desidera generare una sequenza numerica sul database server). Nel caso di Sequenze Servoy, le informazioni vengono memorizzate SU ciascuna sequenza (come “entità da incrementare” che calcola il successivo numero di sequenza) nel repository, ma i numeri di sequenza stessi rimangono nel database. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 25 Tutto ciò che Volete Conoscere sui Foundsets by Adrian McGilly Che cos’è un foundset? Ogni volta che una soluzione Servoy richiede dati dal database, viene creato un Foundset contenente i risultati da una query. Più tardi vedremo il dettaglio di come e dove questo viene fatto, ma per ora pensate solo a l Foundset come a un insieme di records recuperati dal db, e che la soluzione può ‘usare’. Quando i records dati sono contenut i in un foundset, Servoy offre molti modi facili per visualizzarli, ordinarli, editarli, cancellarli, stamparli e genericamente elaborarli. In altre parole, i Foundsets vi sono amici. Quando create una form in Servoy, le indicate su quale db essa deve essere collegata. Questo settaggio è inserito nella proprietà tableName della form e può essere visto nel pannello delle proprietà quando vengono visualizzate le proprietà per quella form. Questo non significa che siete limitati a lavora re solo con le colonne di quella tabella sulla form, ma serve solo come spunto iniziale. (Come vedrete, user emo degli altri ingegnosi strumenti Servoy come le Relazioni e i Tabpanels per acquisire i dati da altre tabelle, ma lo vedremo più tardi.) Per default (predefinizione), le form che sono collegate sulla stessa tabella condivideranno anche lo stesso foundset. Due form collegate alla stessa tabella mostreranno per default gli stessi records quando vengono aperte, e inoltre lo stesso esatto record sarà il record “selezionato” o il record “corrente” in entrambe le form. In caso di bisogno, sarete contenti di sapere che esiste una proprietà su ogni form chiamata “Use Separate Foundset’ che, se posta a true, permette a ciascuna form di avere il proprio foundset. (Notare che questa caratteristica non funziona quando una form viene pubblicata nel web client prima del 3.x) [TOP] 26 È utile sapere che quando la vostra soluzione aggiunge, modifica e cancella delle righe, queste operazioni riguardano sia il vostro foundset di lavoro che il db finale. Così se voi siete su una form con 100 records nel suo foundset corrente e aggiungete cinque records a quella form, il vostro foundset contiene ora 105 records. Se voi aveste cancellato 5 records invece di averli aggiunti, il vostro foundset conterrebbe 95 records. Un modo valido per vedere come i Foundsets si comportano è usare come esperimento una tabella con almeno 500 records di dati. Sfortunatamente, i dati di esempio coi quali viene installato Servoy non contiene molt i records nelle varie tabelle . Voi potete riempire rapidamente una tabella con Servoy. Basta creare una form, collegarla al metodo seguente e poi lanciare il metodo stesso: for (var i = 1; i <=500; i++) { controller.newRecord(); // Servoy genererà automaticamente il pks, ma // voi potete anche riempire il contenuto in // alcuni campi così da avere alcune colonne // di dati per giocarci e ri cercare ancora // es. potete inserire 'Firstname 1', 'Firstname 2', // ...'Firstname 500' nella colonna chiamata //first_name. first_name = 'Firstname ' + i; } Se vi servono ulteriori spiega zioni passo x passo per approfondire questo tema, vedere Creazione di una Tabella con 500 Record in Appendice. Quando avete 500 record nella tabella e una form collegata ad essa, cominciate a giocare con ricerche, inseri menti e salvataggio dei dati, viste di elenchi, viste di record, viste di tabella, ecc. 27 (illustrato di seguito) così da ottenere lo slider (controllo dei records) di default (illustrato sotto) per navigare nei records del foundset. I numeri su questo slider sono abbastanza precisi. Facciamo un esempio. Diciamo che avete una tabella Companies con 500 records. Voi create la form customerForm collegata a quella tabella e poi aprite la form a tempo di runtime (in esecuzione). Quando aprite una form in Servoy, per default verrà creato un foundset che comprende tutti i records della tabella che in questo caso sono 500, ordinato per chiave primaria. Poniamo l’ipotesi che facciamo una query che ci ritorna 450 records. Il foundset ora contiene 450 records, mentre la tabella del db contiene ancora 500 records. Quando la ricerca termina, Servoy carica solamente i primi 200 records del foundset. Questo viene chiamato foundset parziale. Ora potete selezionare nel vostro form i 200 records del foundset 28 parziale e, quando richiesto Servoy automaticamente re cupera i successivi 200 così da avere un foundset parziale di 400 a fronte di un foundset totale di 450 recuperati dalla tabella del database che n e possiede sempre 500. Ora potete selezionare i 400 records del foundset parziale e Servoy quando richiesto, recupererà i rimanenti 50 records e renderà il foundset parziale uguale al vostro foundset. Come funzionano i foundsets? Che cosa avviene realmen te? Per rispondere a questa domanda abbiamo bisogno di guardare di nuovo all'architettura di Servoy. Ricordate che in produzione (non in sviluppo), sono tre i livelli che lavorano in concerto: il server database, Servoy Server, Servoy Client. ( L’ambiente di sviluppo, contiene infatti già una istanza locale dell' Application Server) . Ogni volta che create un foundset in Servoy, voi state creando un oggetto nella memoria d i App Server che monitorizza un certo insieme di cose. L’Application Server recupera un elenco di chiavi primarie (PKs) per tutti i records che si accoppiano nella ricerca, e mantiene in memoria l'elenco. E mantiene anche traccia di: • la “query” che ha creato il foundset, • il numero totale di records presenti nel foundset, • quali records sono mostrati attualmente, e su quali form • quali records del foundset sono attualmente selezionati. • quali records modificat i/cancellati dalla creazione foundset • in quali forms della soluzione questi records sono mostrati • quali altre postazioni Servoy clien ts stanno elaborando questi 29 records (es. in un vero contesto di produzione App Server) • e altre cose di cui ora non dobbiamo preoccuparci. Così quando fate una ricerca che restituisce 450 records, Servoy crea un elenco SUL SERVER ( NON nella memoria del client) dei 450 PKs (codici chiave) nel foundset. Servoy fornisce i 200 PKs al client alla volta, assieme a tutte le colonne dati solo per i records da mostrare sul form. Quando navigate nel foundset, il client sa quali archivi devono essere mostrati e quindi richiede le corrispondenti colonne da app server usando il PKs fornito dal server. Quando richiedete un multiplo di 200 records del foundset, il server spedisce al cliente un altro blocco di 200 PKs. Tornando al nostro esempio, poniamo che Servoy abbia r ecuperato i primi 200 records dei vostri 450 -records e voi avete selezionato il decimo record. Questa è un'illustrazione di ciò che sta facendo: Come programmare la navigazione in un foundset Ora noi sappiamo qualcosa sui foundsets, com e vengono creati e come si implementano. Quali tools sono disponibili al programmatore per navigare e elaborare i foundsets? 30 Ci sono molte funzioni disponibili per gestire i foundsets. La maggior parte si trova nell'albero del Servoy Editor, sotto il nodo controller della form, una coppia di funzioni si trova sotto il nodo foundset e altri ancora si trovano nella classe del databasemanager. Per ora, concentriamoci su alcune funzioni chiave che coprono la maggior parte di ciò di cui si ha bisogno per gove rnare un foundset: Function Description databasemanager. getFoundSetCount(foundset) restituisce il numero totale di records del vostro foundset (non solo quanto è stato restituito finora al client, ma quanti sono in tutto). Nel nostro esempio, sono 450. Notare che sebbene la documentazione Servoy avverte che questa può essere un 'operazione costosa ', in realtà lo è solo se ci sono più di 100.000 records in tabella nel qual caso avrete un leggero rallentamento nella elaborazione che state usando. controller.getMaxRecordIndex() restituisce il numero di records del vostro parziale foundset (es. il numero di records che sono stati forniti al client tramite le chiavi 31 PKs). Nel nostro esempio all’ inizio erano 200, poi andarono a 400 e alla fine 450. Potete ottenere lo stesso risultato con foundset.getSize(). databasemanager. getTableCount(foundset) restituisce il numero di records della tabella sulla quale si basa il foundset. Nel nostro esempio sono 500 controller.getSeletedIndex(n) Seleziona il numero che individua il record nel foundset, nell’esempio è 10 controller.setSelectedIndex(n) restituisce il record attualmente selezionato del foundset (spiegazioni ulteriori più avanti) Forse il più importante di questi comandi è l'ultimo, controller.setSelectedIndex(n) che seleziona l’ennesimo record del foundset. (Il numero indicato a cominciare dal primo record, così selSelectedIndex(5) seleziona il quinto record del foundset). Che vuole dire ‘selezionare le 5 righe del foundset '? Vuole dire due cose: • Visivamente, quella riga sarà mostrata e selezionata sulla form che visualizza il foundset. • Tutti i valori di ogni colonna di quel record saranno caricati nel dataproviders di Servoy per quella tabella, quindi tutti questi valori saranno disponibili ai vostri metodi per leggerli 32 e scriverli. • Se i records che avete selez ionato sono un multiplo di 200, verrà lanciata la ricerca dei successivi 200 records Tornando al nostro esempio, poniamo di aver appena fatto una ricerca per recuperare i primi 200 record s dei 450 del foundset. Se voi fate controller.setSelectedIndex(199) voi state selezionando il 199 ° record nel foundset, e caricando il suo contenuto nel dataproviders. Se fate controller.setSelectedIndex(200) voi potete non solo selezionare il 200 ° record ma potreste avviare la ricerca dei successivi 200 records nel foundset parziale . Attenzione perchè se fate controller.setSelectedIndex(250) se in questo caso voi avete solamente 200 records, non accadrebbe nulla. Altrimenti non potreste selezionare olt re la fine dell'attuale foundset caricato, per farlo dovete indicare il multiplo preciso di 200 per lanciare la ricerca anche dei successivi 200 records. Funzioni Foundset e Funzioni Controller Se guardate il set di funzioni disponibili sotto il nodo del foundset di una form, e poi guardate al set disponibile sotto il nodo del controller, osserverete che sono simili: la maggior parte delle funzioni del foundset esistono anche come funzioni del controller. Perchè ci sono due volte? Qual’è la differenza? Le funzioni del foundset fanno le stesse cose di quelle del controller, solo che le funzioni foundset sono disegnate per lasciarsi inserire in modalità istantanea (es. senza riguardare la GUI in tempo reale), mentre le funzioni del controller riguardano la G UI in tempo reale. 33 Questo in teoria. In pratica, non è così semplice, ma questa discussione va oltre lo scopo di questo manuale e sarà aggiunta in un'altra versione del manuale. La distinzione è valida solo se state elaborando un grande volume di records e volete velocizzare le modifiche. Può essere anche qualche volta utile per aggiungere/ cancellare/ modificare dei records senza mostrarli all'utente. Per ora, la mia raccomandazione è di attenersi alle funzioni del controller eccetto quando se ne avrà un effettivo bisogno. Looping Attraverso un Grande Foundset Una domanda che spesso viene fatta è, come posso scorrere TUTTI i records oltre i soli 200 che Servoy recupera alla volta? L'approccio più facile è fare uso di databasemanager.getFoundSetCount() che recupera il numero totale di records nel foundset. Voi potete catturare quel valore in una variabile locale e poi potete fare un loop dal valore di 1 al valore contenuto nella variabile. Questo il codice: //dichiarazione di una var locale e suo settaggio al numero totale di //records nel foundset var max = databasemanager.getFoundSetCount(foundset) for (var i = 0; i <= max; i++ ) { controller.setSelectedIndex(i); // qui fate un qualsiasi vostro lavoro di cui avete bisogno Da notare che abbiamo saltato il valore max nella variabile locale ma solo quello: for (var i = 0; i <= databasemanager.getFoundSetCount(foundset); i++ ) Ma dati gli avvertimenti di Servoy (discussi sopra) circa l’utilizzo di memoria della funzione getFoundSetCount() sarebbe molto meglio evitare di richiamarla ad ogni iterazione di questo loop. 34 Vi è un altro modo di fare un loop attraverso tutti i records di un foundset: var i = 0 //dichiarazione di una var locale e inizializzata a 0 while ( i <= controller.get MaxRecordIndex() ) { //prima legge il record con l’indice i poi lo incrementa di 1 controller.setSelectedIndex(i++); // qui fate le elaborazioni di cui avete bisogno } Oppure potete fare così: for (var i = 0; i <= controller.getMaxRecordIndex(); i++ ) { controller.setSelectedIndex(i); // qui fate le elaborazioni di cui avete bisogno } In entrambi i casi, quando la variabile "i" raggiunge il valore di 200 o un suo multiplo, la chiamata al setSelectedIndex(i) innescherà la ricerca di un'altro lotto di records, ( contenenti lo stesso valore che verrebbe ricevuto dalla funzione getSize() ) in modo tale che il loop continuerà a girare fino alla fine di TUTTI i records del foundset. Come le Aggiunte, Modifiche & Cancellazioni Influenzano i Foundsets Quando aggiungiamo un nuovo record usiamo controller.newRecord() il record viene aggiunto immediatamente al foundset corrente, ma non è salvato nel db fino a quando viene compiuto un salvataggio. Potete leggere sul salvataggio dati qui. Egualmente, le modifiche vengono salvate subito nel foundset, ma non sono salvate nel db fino a lla esecuzione di un salvataggio. Le cancellazioni avvengono simultaneamente nel foundset e nel db. 35 Per default, Servoy salva le modifiche a un record nel db all’uscita dal record, ma potete cambiare tale comportamento in modo che il salvataggio nel db venga differito fino a una vostra richiesta. Ciò significa che potete modificare molti records, (di diversi foundsets!) prima che questi cambiamenti vengano effettivamente salvati nel db. Il foundset in questo caso è come una specie di area temporanea in cui fare modifiche ai records in attesa di conferma. Nota: questo comportamento non deve essere confuso con le transazioni database, che hanno altri controlli e sono spiegate qui. Automatismo di Aggiornamento & Distribuzione dei Dati L' App Server fà anche del caching molto intelligente in mo do da minimizzare il numero di volte che deve consultare il database, ma lo fà senza compromettere l’aggiornamento dei dati. Inoltre controlla che qualsiasi modifica fatta a qualsiasi records nel foundset venga riflessa su ogni form della soluzione e natur almente anche su qualsiasi altra form in ogni postazione client di Servoy! Per esempio, se cambia te un prezzo unitario da $1.00 a $2.00, che concerne alcuni calcoli di totale su una sub-form in un tabpanel, Servoy si prende cura di aggiornare automaticamente il subform. Inoltre, se un altro utente lavora sulla stessa soluzione e la stessa form che riguarda quel cambio, allora, Servoy Server aggiornerà automaticamente quella form. Direi bello. (Notare che questo si applica solo a chi usa Java client. Per chi usa il web client occorre compiere un refresh del browser per vedere la modifica .) by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 36 Contenitori: Vista di Variabili, Dataproviders, Calcoli e Elementi by Adrian McGilly È importante capire e quindi usare i diversi tipi di contenitori che Servoy offre per immagazzinare e gestire i dati. La documentazione di Servoy spiega bene come poter creare e usare questi contenitori che questa sezione vorrebbe ulteriormente approfondire. Dataproviders Dataproviders è il nome che Servoy dà a un gruppo di co ntenitori che includono i seguenti elementi: • colonne del database • calcoli memorizzati • calcoli non memorizzati • variabili globali (dichiarate nella finestra del Dataproviders, non nel vostro codice JavaScript, pratica da scoraggiare) • aggregazioni Date uno sguardo alle seguenti: Colonne del Database Sono tabelle e colonne dei vari databases servers collegat i e resi visibili alla vostra soluzione. Leggere Dove sono memorizzati gli Schemi DB? per una comprensione di come la vostra soluzione viene accoppiata col vostro schema db. [TOP] 37 Calcoli Memorizzati Ci sono speciali istanz e di colonne del database dove il loro valore viene calcolato da Servoy sulla base d i codice JavaScript scritto da voi in un metodo. Servoy si prende automaticamente cura di ricalcolar e e memorizzare nella tabella i nuovi risultati dovuti alle eventuali modifiche , e gestisce questo per ogni record della tabella. Osserverete che quando siete nei calcoli dell’editor (illustrato in seguito), l’albero è più corto di quello principale nell’ Editor di Servoy. A parte i Globals, gli unici dataproviders mostrati nell'albero sono della tabella sulla quale si sta definendo il calc. Egualmente essa mostra solo relazioni che “iniziano” col nome di quella tabella. Per vedere e gestire qualsiasi altro oggetto occorre andare direttamente su ognuno di essi, form, controller, oggetti foundset, oggetti databasemanager e su tutti gli altri oggetti usati in Servoy Editor. C'è un valido motivo per questo. Sebbene Servoy non vi limita nella scrittura del codice. E’ meglio attenersi a ciò che potete fare usando questo albero. La ragione è che i calcs sono effettuati più spesso di quello che pensate, e inserendo operazioni costose come ricerche, aggiornamenti di records, comandi SQL, lunghi loop, potete degradare significativamente le performance di sistema. 38 Un paio di esempi per spiegare l’uso di un calc memorizzato: Abbiamo una tabella e vogliamo memorizzare una chiave complessa per ciascun cliente basata sul codice zip e sull'anno che il cliente è entrato nel sistema. Così per un cliente con codice zip 94502 entrato nel sistema nel 1997 vogliamo '94502-1997'. Possiamo creare un calc memorizzato chiamato customer_key di tipo char col seguente metodo: return zip_code + ' -' + date_entered.getFullYear(); Ora immaginate che invece di memorizzare quella chiave nella tabella customer, voleste memorizzarlo nella tabella ordini. Per fare questo, avrete bisogno di una relazione moltia-uno chiamata orders_to_customers che collega ogni record ordine al record cliente collegato. Ovvero, il vostro metodo del calc sarebbe così: return orders_to_customers.zip_code + ' -' + orders_to_custo mers.date_entered.getFullYear(); 39 Calcoli Non Memorizzati I Calcs non Memorizzati sono come i Calcs Memorizzati però non vengono mai scritti nel database, vivono solo in memoria.Pensate a loro come a 'calcoli di colonne virtuali' che potete usare nei vostr i metodi e mostrare sulle form ma che non vengono mai scritti nel db . Sebbene i Calcs non Memorizzati di solito sono calcolati come colonne e di solito usati in modalità solo-lettura, questo bisogno non sempre è il caso. Se lo script di calcolo legge sempl icemente come segue: poi piuttosto di calcolare un valore per la colonna, Servoy vi lascerà mettere i valori della colonna nei metodi della vostra soluzione o, se inserite il calc in un campo di una form (e rendete Editabile il campo) Servoy permetterà a gli utenti di registrare i valori del calc. Così ora avete una colonna del database virtuale che voi o i vostri utenti potete manipolare, ma che non verrà mai allocata nel database, e che persisterà solo finchè persiste il foundset. Questo a volte può risultare molto utile, come dimostrato in questo esempio di implementazione di checkboxes. Aggregazioni Le aggregazioni sono come calc s non memorizzati e ricevono operazioni di aggregazione (somme, medie, contatori, max e min) su un foundset di records. Poniamo di visualizzare un elenco di clienti su una form. Una delle colonne della tabella customer è chiamata YTD_total e contiene il valore totale degli ordini di quel cliente inseriti fino a quest' anno. Si vuole mostrare un totale di tutti i valori YTD_total nel foundset corrente sulla form. Questi sono i passi: Create una aggregazione chiamandola sum_YTD_totals sulla tabella customer, 40 Inserire una sezione 'Trailing Grand Summary' in cima alla form Inserire la aggregazione sum_YTD_totals in un campo all’interno della sezione 'Trailing Grand Summary' della form. Presto fatto! Voi potete usare la stessa aggregazione anche con le relazioni per aggregare un gruppo di records correlati senza doverli visualizzare. Costruite l'esempio di cui sopra, con una tabella chiamata salesreps, e una relazione 'uno-a-molti' tra salesreps e customers chiamata salesreps_to_customers. Potreste creare un calc (memorizzato o no, come desiderate) nella tabella salesreps che calcoli il totale di YTD_totals per tutti i clienti che appartengono a quel salresrep. Questo il metodo da usare nel vostro calc: return salesreps_to_customers.sum_YTD_totals Variabili Globali Ci sono due tipi di variabili globali possibili in Servoy, quel lo che voi dichiarate nella finestra del Dataprovider e quello che dichiarate in un metodo JavaScript. Le v ars globali dichiar ate direttamente nel vostro codice JavaScript non vengono mostrate nell'elenco delle vars globali della finestra del Dataprovider, né vengono mostrate in qualsiasi altro elenco all'interno del IDE di Servoy. Sono usati da programmatori JavaScript avanzati, mentre raccomando ai principianti di non fane uso. Le vars globali dichiarate nella finestra di Dataprovider sono disponibili a tutti i vostri metodi e da tutte le chiamate dai dataproviders (es. nei campi sulle forme, nelle definizioni delle relazioni sotto il nodo Globals>>Variable dell'oggetto albero in Servoy Editor, ecc.). Voi assegnate una var globale mettendo 'globals.' dav anti al 41 suo nome, come: globals.lastName = 'Smith'; Le vars globali non persistono quando uscite dall'ambiente di run-time. Se voi con ctrl-L uscite dall'ambiente di run -time mentre state scrivendo e testando in debug un metodo, sappiate che il valore di queste variabili viene convertito in zero o null, (ciò dipende dal tipo di variabile). Potete assegnare un valore di default a una var globale nella finestra del dataproviders, nello stesso luogo dove la create. Come si assegnano i dataproviders nelle fo rm & metodi Prendiamoci un pò di tempo per spiegare come assegnare un campo ai dataproviders nelle form e nei metodi. Per assegnarlo a una colonna di database così: database_table_name.column_name ma Servoy mi ha assegnato la colonna anche in questi modi: forms.form_name.column_name e forms.form_name.relation_name.column_name e la mia immediata reazione er a di dire 'Ma la colonna fà parte di una tabella, non di una form! Come f à a sapere quale è la tabella da assegnare? La risposta è che una form è sempr e collegata ad una tabella, così voi la state assegnando implicitamente alla tabella. Inoltre, quando voi dite forms.customerForm.last_name voi state infatti assegnando la colonna last_name del record attualmente selezionato sulla form customerForm. Così p er esempio se voi voleste settare la colonna last_name a ' Smith ' dovreste fare: 42 forms.customerForm.last_name = 'Smith' e se voleste inserire il valore della colonna last_name nella var globale dovreste fare: globals.cust_last_name = forms.customerForm. last_name Gli esempi sopra stanno usando il prefisso “forms.customerForm” davanti al last_name. Se il metodo che contiene il codice appartiene alla form customerForm, allora potreste omettere il prefisso “forms.customerForm” e funzionerebbe bene lo stess o. In altre parole, voi dovreste invece fare così: last_name = 'Smith' globals.cust_last_name = last_name Dovete applicare le stesse regole di si ntassi quando volete assegnare calcoli o aggregazioni. Assegnare un Dataproviders a i Records Correlati Panoramica Ora guardiamo a come usare le relazioni per assegnare un record correlato dataprovider a un campo della form . Ogni form è collegata a una tabella. Anche ogni relazione è collegata ad una tabella se pensate alla tabe lla sul lato sinistro della definizione della relazione come sua 'tabella base '. Per esempio noi possiamo pensare a una relazione customers_to_orders come ' basata sulla' tabella dei clienti. Le sole eccezioni sono le relazioni globali che sono ‘basate’ a una var globale piuttosto che a una tabella. Lasciamo stare questa parte per il momento. Se create diverse relazioni basate sulla tabella customer, come customers_to_orders, customers_to_salresreps, customers_to_contacts, ecc. queste potrebbero essere tutt e visualizzate (ad es. sotto un tab relazioni) in qualsiasi delle 43 form collegate alla tabella customer (vedi sotto). Voi potete usare queste relazioni per assegnare un dataprovider di tabella correlata (es. una colonna della tabella sulla parte destra della relazione) con relation_name.dataprovider_name Relazioni Molti-a-Uno Se la relazione è molti-a-uno (come customers_to_salesreps la quale per ogni record di un gruppo di clienti assegna un unico record salresrep) allora per fare quest o: forms.customerForm.customers_to_salesreps.last_n ame State dicendo il ‘cognome’ selezionato sulla customerForm che appartiene alla tabella ‘settori clienti’ correlata alla tabella ‘clienti’. 44 Come con i dataproviders non correlati , la espressione forms.customerForm.è necessaria solo se siete in un metodo che non appartiene al customerForm. Così se voi volete mettere il cognome (presente nei reparti vendite) sul form customerForm, dovrete creare un campo e specificar gli come dataprovider: customers_to_sa lesreps.last_name anche quando siete in metodi all’interno della customerForm. Relazioni Uno-a-Molti Se la relazione è uno -a-molti (come customers_to_orders che collega un cliente al gruppo di ordini di quel cliente) allora potreste voler usare la relazione insieme a un related tabpanel o a un portale. Potete saltare a la sezione sui tabpanels per vedere come le relazioni uno -a-molti sono usate con i tabpanels, perché l'argomento di cui sotto non è previsto. Lo sto includendo solo per completezza. Quando voi dite: forms.customerForm.customers_to_orders.order_dat e state dicendo 'la data dell'ordine dal gruppo di ordini del cliente attualmente selezionato sulla form custo merForm.' Questa espressione viene usata normalmente nel vostro codice, ma non la vedrete usata come dataprovider di un campo su una form. Lasciate che vi spieghi. Se voi mettete un campo sulla form customerForm il cui dataprovider è: customers_to_orders.order_date mostrerà davvero la data del l 'ordine attualmente selezionato per il cliente attualmente selezionato', ma cosa intende per 45 'ordine attualmente selezionato'? Se voi non state mostrando l'elenco degli ordini collegati, l' ut ente non ha il contesto per sapere quali ordini sono in selezione. Per default, è sempre l'ordine con la chiave primaria minore fra gli ordini collegati a quel cliente, ma manca il contesto dal quale il vostro utente lo può vedere. Per poter selezionare il secondo ordine del gruppo di ordini collegati voi potete caricare questo comando in un metodo: customers_to_orders.setSelectedIndex(2); e appena fatto questo, il campo order_date del secondo ordine correlato al cliente (in ordine di chiave primaria) dov rà apparire sulla form. Sebbene vi siano situazioni dove questa potrebbe essere l'interfaccia desiderata, è più comune usare una relazione 'uno-a-molti' per mostrare le informazioni di tutti i records legati a un parent, oppure mostrare le informazioni co rrelate ai tabpanels (o ai portali). Uso di Dataproviders correlati in TabPanels Ora immaginate di volere mostrare il contenuto d el campo order_date di ogni ordine collegato a un cliente. Dovreste creare un tabpanel correlato sul form customerForm collegato alla relazione customers_to_orders. Nel tabpanel voi inserite una form collegata agli Ordini, e su quella form mettete un campo 'order_date' come suo dataprovider. Questo comanda a Servoy di mostrare nel tabpanel tutti i records degli Ordini collegati al cliente corrente, e specificamente mostra re la colonna order_date di ogni record. Notate che non dovete inserire il seguente comando customers_to_orders.order_date Invece, la relazione customers_to_orders è già sp ecificata nella definizione del tabpanel, e Servoy la usa per la ricerca al 46 momento del caricamento del tabpanel con i records Ordini . Per dettagli sulla creazione dei tabpanels vedere qui. Uso di Dataproviders correlati nei Metodi Ora scriviamo un metodo con un loop per leggere il contenuto di order_date in ogni ordine collegato al cliente selezionato, per poter ottenere la data più vecchia. (Naturalmente potreste fare questo senza scrivere alcun codice usando una aggregazione correlata, che per il momento ignoriamo.) In quel contesto voi dovreste scrivere customers_to_orders.order_date Di seguito spieghiamo come dovrebbe essere il metodo. In questo codice di esempio presum iamo che il metodo appartenga alla customerForm, e così possiamo omettere 'forms.customerForm.'. Presum iamo anche di aver verificato prima di chiamarlo, che è presente almeno un record ordine riferito al cliente corrente ( col controllo che customers_to_orders. getSize() sia maggiore di zero): var most_recent = new Date(); /* questa var locale dovrà contenere la data più_recente. Inizializzata alla corrente datetime. */ for (var n = 1; n <= customers_to_orders.getSize(); n++) { customers_to_orders.setSelectedIn dex(n);/* questo causa la lettura del record 'n' come record corrente , e il suo contenuto caricato nel campo del dataproviders collegato.*/ if (customers_to_orders.order_date <= most_recent) { most_recent = ustomers_to_orders.order_date; } 47 } return most_recent; Uso di Relazioni e Dataproviders Nidificate Nella sezione relazioni nidificate, spieghiamo come potete concatenare insieme delle relazioni per arrivare a un dataprovider più distante, come questo: relation1.relation2.relation3.dataprovider Uso del selectedrecord per assegnare un Dataproviders In Servoy Editor, se voi cliccate sul nodo “selectedrecord” sotto qualsiasi form dell'oggetto albero, voi vedrete l'elenco di dataproviders per la tabella alla q uale la form è collegata. Vengono incluse le colonne del database, calcs memorizzati, calcs non memorizzati e aggregazioni. Voi potete inserire la referenza di un dataprovider nel vostro metodo semplicemente con un doppio -click sul dataprovider di questo elenco. Elementi Quando cominciai a imparare Servoy avevo la difficoltà di capire la differenza tra dataproviders e elementi. Questo perchè un dataprovider e un elemento possono avere lo stesso nome, e questo crea confusione nel decidere quando usarli. Ne l caso voi aveste lo stesso problema, questa sezione intende chiarirlo. Un dataprovider è un contenitore che contiene dati. Questi possono essere messi ovunque, in una colonna del database , all'interno di form, di var globale, di calc o aggregazione. Un elemento è un oggetto visuale su una form come un campo, un'etichetta, un bottone, portale, tabpanel, javabean, un grafico, ecc.. Dovete assegnare un nome a un elemento della form se poi vol ete manipolarlo (es. controllare la sua visibilità, ordinarlo in ordine di grandezza, colore, posizione, se editabile, ecc.) 48 Poniamo di lavorare su una form chiamata customerForm collegata alla tabella customer. Quando aggiungete campi alla form usando il Elements/ field, vi offre la possibilità o meno di inserire il no me per ognuno dei campi aggiunti alla form. Se selezionate questa scelta mentre aggiungete un campo “ last_name” alla vostra form, voi avreste un campo il cui nome è last_name e il cui dataprovider si chiama 'last_name'. Questo può creare un pò di confusion e. Ciò che molti sviluppatori fanno è di nominare gli elementi di un form cliccando su ognuno di essi e inserendo un nome nella proprietà name del pannello della proprietà. (Vedere la sezione convenzioni sui nomi per ulteriori informazioni su questo argomento). Voi potreste usare il prefisso 'fld' quando nominate un elemento di campo (es. fldLastName e fldFirstName), un prefisso 'lbl' per elementi di etichetta (es. lblLastName, lblFirstName) e 'btn' per i bottoni (es. btnLookupAccountBalance). Avendo fatto questo, voi potete modificare ad esempio le proprietà del campo così: forms.customerForm.elements.fldLastName.visible = true forms.customerForm.elements.fldLastName.setFont('Aria l') ma potete ottenere o modificare il valore della colonna last_name (o dataprovider, usando la terminologia di Servoy) come segue: forms.customerForm.last_name = 'Smith' // settaggio della colonna last_name del record corrente a 'Smith' globals.cust_last_name = forms .customerForm.last_name /* inserisce la colonna last_name del record corrente nella variabile globale globals.last_name. * / Gli esempi sopra mostrano il “forms.customerForm” col prefisso solo per chiarezza. Se il metodo che contiene il codice è un metodo della form customerForm, allora voi potreste sempre omettere il prefisso “forms.customerForm” e funzionerebbe lo stesso. In altre 49 parole, voi potete modificare le proprietà dei campi così: elements.fldLastName.visible = true elements.fldLastName.setFont( 'Arial') e voi potete ottenere o modificare il valore della colonna di database last_name così: last_name = 'Smith' // setta il contenuto della colonna last_name del record corrente a 'Smith' globals.cust_last_name = last_name /* mette il valore di last_ name del record corrente nella var globale (predefinita) globals.last_name.*/ In Servoy Editor, se cliccate sul nodo “elements” di qualsiasi form, vedrete l'elenco degli elementi nominati su quella form. Quando cliccate su un elemento, vedrete le sue prop rietà e le sue funzioni elencate sotto. Voi potete inserire la istanza di una proprietà di un elemento o di una sua funzione nel vostro metodo semplicemente con un doppio-click sull'elemento desiderato di questo elenco. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 50 51 52 53 54 Molti Controllers, Meno Tempo by Adrian McGilly È facile confondersi tra i vari oggetti della form che possiedono la parola 'controller' al loro interno, essi sono: • oggetto controller • oggetto currentcontroller • controller form (in Servoy versions precedente a 3.x) Queste le differenze: Oggetto c ontroller Ogni form possiede un controller. Questo non è un oggetto che potete vedere sulla vostra form, come un campo o un b ottone. È visibile solo nell'oggetto albero di Servoy Editor sotto ogni form. Il controller di una for m è una raccolta di proprietà e di metodi che agiscono sulla form e sul suo foundset. Essi includono: controller.find() controller.search() controller.deleteRecord() controller.setSelectedIndex() etc. Oggetto c urrentcontroller currentcontroller significa 'il controllore della form corrente, e per 'form corrente' significa la form che è attualmente visibile. (Ci possono essere al massimo due form visibili se voi includete una form mostrata all'interno di un dialog con showFormInDia log(), ma non è il nostro caso) Questo oggetto è utile quando il vostro codice ha bisogno di fare qualche cosa alla form che è attualmente visibile, ma non potete sapere in anticipo ciò che quella form farà a un dato momento. [TOP] 55 Per esempio, poniamo che state scrivendo un metodo globa le che è responsabile di stampare il contenuto della form corrente. Potreste usare currentcontroller.print() che r ichiama il metodo print() dell'attuale form visibile. In alternativa, poniamo di aver creato il metodo di stampa chiamato myPrint in ciascuna form della vostra soluzione, e supponiamo che volete un metodo globale che richiami il metodo myPrint della form corrente. Come fare se non sapete quale sarà la form corrente in quel momento? Potete usare currentcontroller.getName() per ottenere il nome d ella form attuale, e poi siete pronti per costruire una chiamata al metodo myPrint del vostro form. Così: var formName = currentcontroller.getName() forms[formName].myPrint() (Sto usando il fatto che i raggruppamenti nell'albero di Servoy Editor come 'for ms', 'elements', 'tutti i dataproviders' possono essere trattati come schiere. Così forms.myForm è lo stesso che dire forms[‘myForm’].) Controller Form L'ultimo oggetto con nome ‘controller' è il controller della form. Fino al 2.2.5, ogni form ha una propr ietà nel pannello della proprietà chiamato controller. Qui si può specificare il no me di una speciale form che si vuole che appaia alla sinistra della vostra form ogni volta che viene aperta. Normalmente il controller form viene adoperato come tool per po ter agilmente navigare attraverso i dati della form principale. Dal 3.x è stato cambiato il nome della proprietà a Navigator e la form a Navigator. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 56 57 Come & Quando il salvataggio dei Dati Modificati by Adrian McGilly Panoramica sui Salvataggi in Servoy Nota: l’argomento ha subito cambiamenti dal 3.x, riferirsi a lla fine di questo capitolo per il funzionamento nel 3.x. (Quando parleremo di salvataggio si intenda: attuazione delle modifiche effettuate ). Per ora, presumiamo di non stare usando operazioni del db. La discussione sull' uso di operazioni del d b è più avanti, ma si dovrebbe leggere prima questa sezione. Poniamo che un utente abbia modificato o aggiunto un record su una form. Il comportamento di default di Servoy salva le modifiche o le aggiunte fatte dagli utenti appena cliccano su qualsiasi pa rte della form, o appena si esce dal record in elaborazione. Il salvataggio viene eseguito solo quando viene modificato o aggiunto ogni record, non in altri casi. Le azioni dell'utente che determinano il salvataggio sono: • navigare ad un altro record nella stessa form • aggiunta di un altro record • cancellazione di un record • compiere una ricerca • navigare a un altro form • chiudere la soluzione • uscire da ambiente Servoy La stessa regola del salvataggio dati è valida in Servoy per le [TOP] 58 modifiche eseguite all'intern o dei metodi. Se il metodo fà una modifica a un record, i cambiamenti saranno salvati al db appena il metodo o l'utente esegue qualcuna delle azioni elencate sopra. Per esempio, se il vostro metodo modifica un record A e poi seleziona un rec B (usando con troller.setSelectedIndex () ), i vostri cambiamenti vengono salvati al momento che B viene selezionato. Considerate questo metodo: controller.newRecord() name = 'ABC Company' city = 'Fremont' return; Immediatamente subito dopo il compimento del primo comando di aggiunta record, voi vedete 'ABC Company' e 'Fremont' che vengono inseriti nei loro rispettivi campi sulla form, ma sia questi valori che il nuovo record stesso non vengono salvati effettivamente sul db fino a quando un metodo o un utente compie una delle azioni sopra elencate. Un altro esempio: controller.newRecord() name = 'Furtado Auto Supply' city = 'Livermore' controller.newRecord() name = 'Honest Ed Auto Repair' city = 'Larksp ur' return; Immediatamente dopo il compimento di questo metodo, il record 'Furtado Auto Supply' viene già salvato nel db, invece quello 'Honest Ed' sebbene visibile sul form, non viene salvato ancora. Ora guardiamo alla cancellazione e Controller.delet eRecord() cancella immediatamente il record sia dal foundset che dal db – non è necessario nessun salvataggio esplicito nè altre azioni. 59 Preferirei però usare controller.saveData() esplicitamente alla fine del metodo che ha modificato i dati, giusto per essere sicuro. Ci sono delle importanti eccezioni alle regole sopra descritte. Uso del setFocusLostSaveEnabled(false) C'è la funzione application.setFocusLostSaveEnabled() che può essere usata per cambiare il comportamento su esposto. Se inserite questo comando con false, dite al sistema di bloccare il salvataggio delle modifiche ogni qualvolta l'utente clicchi su un'area vuota della form. Le modifiche però continuano a essere salvate automaticamente quando l'utente compie qualcuna delle azioni per uscire dal record modificato/aggiunto specificate nell’elenco sopra. Uso di Transactions Se state usando transactions, allora tutto ciò detto sopra viene applicato, a meno che le modifiche siano state effettu ate all'interno di una transactions non ancora connessa al db , ciò determina il reale salvataggio dei dati solo alla effettiva connessione al database. Se fate diverse modifiche (es. aggiunte, cancella zioni, modifiche) all'interno di una transaction, esse interesseranno il foundset ma non il db fino a quando eseguirete un commit. Inoltre, se la transaction è annullata(rolled back ), i cambiamenti effettuati vengono annullati anche loro, sia nel foundset che nel db. I comandi per gestire le transactions sono: Command Description databasemanager.startTransaction() Lancia una nuova transaction databasemanager.commitTransaction() Conferma esecuzione corrente transaction databasemanager.rollbackTransaction() Annulla la transaction 60 Cambiamenti in Servoy 3.x Con Servoy 3.x molte cose sono cambiate. Servoy ha aggiunto una opzione chiamata autoSave con la quale potete attivare oppure no i salvataggi automatici con databaseManager.setAutoSave(boolean). Quando autoSave è on, attua il comportamento descritto per la versione 2.2.5. Quando autoSave è off, Servoy blocca i salvataggi in proprio–essi dipenderanno da quel punto in poi dal comando saveData() con un parametro di temporizzazione per il db server. Questo è stato fatto per permettere di armonizzare il comportamento del rich client con quello del web cliente. Nel web client, Servoy non può sapere che un utente sta “uscendo da l record”, questo è possibile nel rich client, e perciò in questo caso non può offrire il salvataggio automatico dei records sui forms che girano sul web client. Settando il comando autoSa ve in off si fà in modo che le form si comportino allo stesso modo a riguardo del salvataggio dei dati, sia nel rich client che nel web client. Se mettete autoSave in on o in off, voi lo fate per la vostra intera soluzione . Se desiderate settare a on alcune form e a off altre, voi lo potete fare alla apertura e alla chiusura di ciascuna form. Servoy ha presentato un secondo uso del comando saveData(). Prima del 2.2.5 il comando saveData faceva parte dell'oggetto controller e così forms.customerForm.controller.saveData() salv ava le modifiche eseguite solamente sulla form customerForm. Il nuovo comando presentato col 3.x è databaseManager.saveData () che salva le modifiche su tutte le form. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 61 Convalida dei Record Prima di Salvare by Adrian McGilly Panoramica sulla Convalida dei Dati Servoy possiede alcuni controlli di questa funzionalità risultata un pò debole nella versione 2.2.5 mentre è stata migliorata nel 3.x. I principianti, dovrebbero fare localmente la convalida , con i metodi JavaScript. Se vi aspettate che il vostro db spedisca messaggi su UNIQUE o sulle violazioni di NOT_NULL e REFERENTIAL INTEGRITY , esse saranno nella forma brutale “Cannot save form data” che riporta il messaggio dir etto dal database–non qualcosa che desiderate per i vostri utenti. Nel 2.2.5 non c'era questa modalità. (Nel 3.x si possono intercettare i messaggi del database e gestirli in modo elegante. Non ho ancora usato questa funzionalità del 3.x quindi non ho ancora elementi per giudicare.) Ci sono tipicamente, due livelli di convalida –a livello di campo e a livello di record. La convalida a livello -campo è quella dove controllate che ogni singolo campo contenga un giusto valore, e la convalida a livello-record è dove controllate che i valori del campo siano congrui con il valore degli altri campi –per esempio controllare data di inizio e data di fine, con la data di inizio inferiore della data di fine. Servoy permette la convalida di entrambi i livelli. Per la convalida a livello-campo, potete collegare un metodo di convalida all'evento onFocusLost (alla uscita dal campo) o all'evento onDataChanged ( appena il contenuto del campo viene cambiato). Potete fare poi i vostri controlli di convalida all'interno del metodo collegato all'evento del campo e se la convalida fallisce e volete permettere all'utente di lasciare il campo, inserite il seguente comando: elements.your_field_element_name.requestFocus(); [TOP] 62 Voi non potete fermarlo. Questi eventi a livello -campo lanciano il metodo solo se state lasciando un campo per andare a un altro campo dello stesso record. Invece se cliccate su un tasto che vi porta su un altro record o su un altro form, o se siete in list view o table view e cliccate su un campo di un record divers o dell'elenco, tutti questi eventi non lanciano. Così anche se aggiungete tutti questi controlli a livello -campo, siete costretti per sicurezza a controllare di nuovo i campi per la convalida a livello -record. La miglior convalida a livello-record è l'evento onRecordSave. Questo evento funziona ogni volta che si esce dal record modificato. Viene applicato senza controllare COME si esce dal record, e senza controllare se si sta mostrando il record in modalità record view, list view or table view. Per esempio, se parliamo di un record (in list view or table view) e si esce da esso cliccando su un’altro dello stesso elenco, oppure su un qualsiasi record della stessa form, o si è cliccato su un bottone che vi porta su di una diversa form. L’evento onRecordSave lancerà con nessun riguardo a come l'utente lascia il record. L'unico problema era prima del 2.2.5, dove non c'era alcun modo di dire all'evento onRecordSave di non salvare il record se falli va la convalida. Potevate fare il vostro metodo di convalida per controllare la validità di un dato, ma quando l'esecuzione finiva, Servoy salvava lo stesso i dati. Questa era una svista , che rendeva la convalida del livello -record molto difficile. Dal 3.0 è stato modificato questo evento così che se il meto do collegato ad esso riceve un false evita il salvataggio . Tre differenti approcci Ci sono alcuni modi di lavorare su questo probl ema. Di seguito i tre migliori: Fare modifiche e aggiunte con una finestra di dialogo Potete fare tutte le modifiche in Record View usando una 63 finestra di dialogo . application.showFormInDialog(forms.formName) dove mostrate la form specificata in una finestra di dialog. Così se la form specificata contiene il record che è stato aggiunto/modificato, questo approccio mantiene la sicurezza per l’utente nell’inserimento e nella modifica del record essendo limitato ogni volta a un solo record su ogni form.In questo caso voi avrete bisogno di mettere un paio di tasti salva & cancella sulla form, e quando si preme il tasto salva, voi potete lanciare la convalida e salvare i dati col comando controller.saveData() se la convalida risulta giusta. Bloccare o intercettare tutti i punti di uscita dal record Un altro approccio è la modifica/aggiunta con una normale form sulla quale inserire i tasti salva & cancella (o sulla form controller, se la state usando) per verificare che l'utente non possa andare da alcuna parte prima che l’operazione sia stata salvata o annullata. Di seg uito vengono presentate alcune tecniche per realizzarlo: 1. Non si permette all'utente di lasciare la form se si riceve un false dal metodo e poi collegarlo ad esempio all’evento onHide. In questo modo, se quel metodo potesse controllare la convalida, allora in caso negativo potrebbe mostrare un messaggio bloccante che non permetta all’utente di lasciare la form. 2. Si può disabilitare una intera form settando la proprietà enabled a false. Questo può essere utile con una controller form o una form all’interno di un tab panel con i tasti per la navigazione e si vogliono subito disabilitare tutti quei bottoni. 3. Si vorrebbe anche prevenire l'utente dall’effettuare le operazioni dal menu Select (come Next, Previous, New Record, ecc.) per aggiornare o inserire ogni 64 record. L'unico modo per prevenire queste operazioni, è quello di esaminar e ogni metodo che viene lanciato dal corrispondente evento (es. onNextRecordCmd, onPreviousRecordCmd, onNewRecordCmd, ecc.) e per ogni metodo esaminare se il record corrente è in stato non valido prima di procedere col percorso normale.Per esempio, si potr ebbe usare l'evento onNewRecordCmd per chiamare il vostro metodo myNewRecordCmd, e questo metodo dovrebbe esaminare prima se il record corrente è in uno stato non valido. In tal caso, dovrebbe avvertire l'utente con un messaggio bloccante. Altrimenti, crea re un nuovo record usando controller.newRecord. 4. Attenzione perchè scegliendo questo approccio userete application.setSaveOnFocusLostEnabled(false) (discusso sotto) perché altrimenti, nel momento in cui un utente clicca sul proprio tasto save Servoy lancerà il salvataggio del record e bypasserebbe così la vostra convalida. Uso delle transazioni Forse l’ approccio più semplice è di usare una transazione. Se includete un add o un edit in una transazione, allora non dovete più preoccuparvi di un salvataggio prematuro dei vostri dati perché al momento del fallimento della convalida potete ritornare indietro al onRecordSave. Attenzione perchè questo non impedirà al db di generare errori, come violazioni di record unique o violazioni di campi not_null durante il salvataggio dati, così avrete bisogno di verific he come spiegato di seguito qui. Funzione setSaveOnFocusLostEnabled() La funzione application. setSaveOnFocusLostEnabled () controlla la chiamata di onRecordSave . Se è messo a true, onRecordSave agirà nel momento in cui l'utente va su un altro record o clicca su 65 una parte libera della form. Se è messo a false, quella stessa azione non attiverà onRecordSave. Comportamento di Modifiche e Salvataggio Prima del 3.x Ci sono un paio di importanti miglioramenti in quest o argomento nella versione 3.0. Il più importante è, come menzion ato sopra, che voi ora potete fermare l'evento onRecordSave per compiere un salvataggio semplicemente restituendo un false al metodo onRecordSave. Inoltre, come menzion ato in una precedente sezione del manuale, la versione 3.0 ci lascia “spegne re autoSave”, e se voi avete il completo controllo dei dati–essi non saranno MAI salvati senza il vostro esplicito comando di saveData. Queste due migliorie renderanno più facile la implementazione di convalida a livellorecord. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 66 Verifica Univocità di un Record by Adrian McGilly Quando aggiungendo o modificando un record , spesso avrete situazioni dove vorrete verificare che una certa colonna o gruppo di colonne sia unico per quella ta bella. Come fare questo in Servoy? Ci sono diversi modi per farlo. Se non vi importa che i vostri utenti ricevano un brut ale messaggio, potete mettere la restrizione uniqueness sulla tabella del vostro db e potete contare su quella. In questo caso, quando salvate il record , i vostri utenti riceveranno un bip e un messaggio di errore simile a “non si possono salvare Dati del Form”. Se l'utente clicca sul tasto “ Details” sotto il messaggio vedrà un messaggio del database che cita una violazione della restrizione. Non è molto bello. Sfortunatamente in 2.2.5 non vi è modo di “intercettare” questi messaggi del db per poterlo presentare meglio all'utente. (Questa funzionalità comincia dal 3.x) L'altro approccio deve verificare l' uniqueness interrogando il database per vedere se ci sono records duplicati prima del salvataggio di un nuovo record. In tal caso, voi dichiarate una violazione di uniqueness all’utente nel modo migliore che ritenete , e ritornate all'utente il record senza salvarlo. Altrimenti lo salvate. Questo sembra abbastanza semplice, ma c'è un inghippo. Poniamo che il vostro utente abbia aggiunto un nuovo record su una form customerForm, la quale è collegata alla tabella Customer. Lui riempe i suoi campi inserendo ‘ACME Tools’ nel campo company_name. Poi preme il tasto save. Voi avete già programmato il tasto save per verificare l'uniqueness del company_name prima di salvare il record. Voi fareste così: // inserisce il campo del nuovo record in una var locale var co = company_name 67 controller.find(); // lancia una sessione di ricerca company_name = co; // gli dice di cercare su company_name = co controller.search(); /* lancia la ricerca e mette i risultati nel foundset corrente */ if (controller.getMaxRecordIndex() ) { plugin.dialog.showErrorDialog('Uniqueness Violation', 'C’è già una s ocietà con il nome ' + co, 'OK'); } else { controller.saveData(); } Il motivo per cui non eseguirà il lavoro è che nel processo di ricerca dei records duplicati, voi avete già pulito il foundset precedentemente contenut o nella form, quando il foundset conteneva il nuovo record. Quando il vostro metodo arriva al comando savedata(), non avrà più accesso al nuovo record che volevate salvare. Nell'esempio di cui sopra, l'utente aveva aggiunto un nuovo record. Lo stesso si applica se l'utente modifica un record esistente, e voi volete verificare l' univocità del record modificato . Ora, rimanendo sull’esempio di sopra (controllo della univocità della colonna company_name della tabella Customer sul form customerForm) vi mostrerò un paio di modi per controllare uniqueness senza toccare il vostro foundset: Approccio #1 – scrivere una generica funzione checkUniqueness() con SQL Potete usare una query SQL per determinare la univocità. Le query SQL si lanciano con databaseManager.getDataSetByQuery () senza interferire con i foundsets (a meno che non lo richiedete!). databaseManager.getDataSetByQuery () lancia una query SQL al 68 vostro db e ottiene indietro come risultato un dataset. Per default, questo comando non concerne foundsets in alcun modo così funzionerà perfettamente nella nostra situazione. Poniamo di avere una form customerForm con un metodo della form chiamato “Sa ve” di cui supponiamo esaminare l’univocità di company_name della tabella Customer . Se risultasse unico, il record sarebbe salvato, altrimenti mostrerebbe un messaggio di errore. Nell’esempio successivo usiamo una funzione SQL . La funzione count(*) è una funziona SQL standard per contare tutt i i records che vengono confrontati col criterio determinato dalla clausola where. Il metodo dovrebbe essere così : /* conta il numero di records con uguale contenuto di company_name . Questa query deve ritornare un numero, così il dataset risultante sarà una schiera 1 x 1. */ var query = 'select count(*) from Customer where company_name = ' + company_name; var resultDataSet = databaseManager.getDataSetByQuery( controller.getServerName(), query, null, 1); /* la funzione getValue prende come suo parametro un numero di record e un numero di colonne e restituisce il valore nella casella del dataset. Se è uguale a zer o, allora nessun record trovato nel db significa che quel record creato è unico. */ if (resultDataSet.getValue(1,1) == 0) // testa il numero di record contati { // il record è unico controller.saveData(); } else { plugins.dialogs.showErrorDialog('Error', 'Un cliente con company name ' + company_name + ' esiste già. ', 'OK'); 69 } Ora starete pensando “que sto è un terrificante insieme di codice per esaminare l' univocità di un record!” e avete ragione. Ma questo si potrebbe ridurre tutto a una chiamata di una riga mettendo tutto questo codice in una funzione globale “checkUniqueness”. Una volta fatto, il vostro test sulla univocità sarà semplice come questo: if (globals.checkUniqueness('Customer', 'company_name', company_name)) { controller.saveData(); } else { // show your error dialog here } Questa funzione adopera come parametri il nome ta bella, il nome colonna e il valore che deve essere esaminato nei dati, e restituisce vero se il record è unico, e falso se non lo è. La funzione sarà: /*************************************** FUNCTION: globals.checkUniqueness() SCOPO: controlla se un record è unico per una data tabella. Restituisce true se si, false se no PARAMETRI: 1. nome tabella, 2. nome di colonna che deve essere u nico, 3. valore del test for uniqueness ESEMPIO DI CALL: Il seguente codice di esempio restituisce true se non ci sono righe in tabella client con il valore 'Smith' nella colonna name : globals.checkUniqueness('clients', 'name', 'Smith') ************ ****************************/ 70 var tableName = arguments[0] var columnName = arguments[1] var columnValue = arguments[2] /*Nelle prossime due righe di codice facciamo uso di una caratteristica della getDataSetByQuery che rende più facile legare i nomi del le colonne ai valori delle costanti all’interno della clausola WHERE mettendo dei punti interrogativi dove volete che appaia il vostro literal(s), e inviando il literal come terzo parametro di getDataSetByQuery. Questo parametro sarà una schiera perchè abbiamo posto columnName in [] – e questo crea una schiera con columnName come suo unico membro. Il primo parametro è currentcontroller.getServerName() la quale restituisce il nome del db server al quale la form è collegata.*/ Questo parametro deve essere un o rdine che è perchè noi mettemmo columnName in [] –questo crea un ordine con columnName come il suo unico membro. var query = 'select count(*) from ' + tableName + ' where ' + columnName + ' = ?'; var resultDataSet = databaseManager.getDataSetByQuery( currentcontroller.getServerName(), query, [columnName], 1) if (resultDataSet.getValue(1,1) == 0) //restituisce il valore nella singola -casella dataset. Se è uguale a zero, allora non ci sono matching record nel db così il record creato è unico. { return tr ue; } else { return false; } Se ne aveste voglia, potreste migliorare questa funzione per supportare costrizioni di uniqueness di colonne -multiple permettendo la chiamata per spedire i nomi di colonne multi ple e il 71 valore di colonne multiple ognuna all’interno di una schiera. Qualche cosa da tentare nel vostro tempo libero! Approccio #2 – uso di una relazione per test di uniqueness Voi potete creare una relazione globale di test per uniqueness. Questo vi risparmia la scrittura di codice SQL, però dovete creare una relazione per ogni colonna di cui desiderate esaminare l’univocità. (Le relazioni sono discusse e molto dettagliate nel capitolo chiamato Le Relazioni – voi potreste leggerlo e poi ritornare qui.) Il nostro esempio, dovrebbe essere: 1. Creare una var globale chiamata testValue. 2. Creare una relazione testValue_to_company_name 3. Settare la chiave primaria ( lato sx) con globals.testValue 4. Settare la chiave esterna (lato dx) con la colonna company_name della tabella customer Ora avete una relazione che punta a tutti i records di Customer la cui colonna company_name si accoppia con globals.testValue. Voi potete usare questo per esaminare l' univocità di quel valore esaminando la ‘size’ delle relazioni del foundset usando la funzione getSize(). Tornando al nostro esempio: l ’utente ha appena inserito un record Customer e lanciato il salvataggio. Voi volete esaminare l'univocità del campo company_name. Qu esto è il vostro metodo: if (testValue_to_company_name.getSize () == 0) { // il record è unique controller.saveData } else { // il record non è unique. Visualizza error 72 msg, ecc. } Potete naturalmente riutilizzare globals.testValue in qualsiasi altr a relazione globale di cui avete bisogno per esaminare l’univocità di altre colonne. Approccio #3 – uso di foundset separato per ricercare matching record (Questo approccio gira in 3.x con autoSave a off. Non in 2.2.5 perché lancia un salvataggio che aggira le regole di convalida) Se nessuno di questi approcci vi attrae, e volete seguire la modalità base con i comandi find() /search () per esaminare l’univocità, voi potete farlo in modo da non disgregare il foundset della form che contiene il nostro nuovo record. Voi potreste, per esempio, crear e una form nuova collegata alla tabella Customer, attivare la sua proprietà useSeparateFoundset e lanciare la find() /search() usando il controller di quella form. Di seguito viene evidenziat o: La form sulla quale il record è stato inserito è customerForm, ed è la form attualmente mostrata. La form sulla quale voi farete la find()/search() per determinare l’univocità sarà customerLookupForm. Di seguito vi è un metodo sulla form customerForm per esaminare l’univocità del campo company_name: var co = company_name customerLookupForm.controller.find() customerLookupForm.company_name = co customerLookupForm.controller.search() if (customerLookupForm.controller.maxRecordIndex == 0) { /* il record è unique, così lo salvate usando il controller del form attuale mostrato , customerForm*/ 73 controller.saveData } else { // il record non è unique - mostrate error msg, ecc. } by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 74 Come Trovare le Date by Adrian McGilly Panoramica sulle Date in Servoy Questa sezione tratta d ella ricerca sulle date, un utente cerca su una form, o lo sviluppatore codifica la ricerca all’interno di un metodo. Prima di andare avanti, avete bisogno di sapere due importanti cose sui campi delle date in Servoy: • Per default, Servoy usa campi datetime (non campi date) per memorizzare le date. • Il formato di visualizzazione di un campo data dipende dal modo con cui i dati sono stati inseriti nel campo e viene interpretato sia in modifica che in ricerca per quel campo. Prendiamoli in considerazione uno per volta . Servoy per default usa campi datetime Per default, quando create campi data in Servoy state in realtà creando campi datetime, cioè nel medesimo campo verranno allocati la componente data e la componente tempo: 2005-12-20 00:00:00.000 oppure 2006-03-14 17:23:45.212 (le ultime tre cifre sono in millisecondi). Per il resto di questa discussione noi toglieremo i millisecondi poichè vedremo che non vengono quasi mai usati nelle applicazioni. Quando compilate i dati nelle form e inserite la data in un [TOP] 75 campo datetime, per default nel campo non sarà registrato alcun componente tempo. Così se inserite 12-20-2005 per default Servoy dovrà allocare nel campo 12-20-2005 00:00:00 È più probabile vedere la componente tempo in un campo data quando un metodo registra un timestamp (e s. timestamp di modifica, timestamp di creazione. Consiglio: Servoy registra automaticamente per voi il timestamps di modifica e di creazione - guardate alle particolari colonne in molte tabelle del database , si vedrà che quei valori vengono inseriti automaticamente dal sistema .) Il formato di visualizzazione date può essere gestito In secondo luogo, dovete sapere che il formato col quale le date sono mostrate (es. MM-dd-yyyy) sulle form viene controllato dallo sviluppatore . È indipendente dal formato delle date nel db. Controllate la visualizzazione di default dei campi configurando gli opportuni parametri in Modifica>> Preferenze, ma voi avete la priorità sulla configurazione di default per modificare il formato dei campi data su qualsiasi form specificando un formato di visualiz zazione diverso. 76 Da notare che la modifica del formato fatto su uno specifico campo, riguarderà solamente quell’elemento di campo, su quella form. Se avete una colonna 'start_date' di database che compare su diverse form, essa può possedere, se necessario, un formato diverso su ciascuna form. (Il formato col quale il db memorizza la data è indipendente dal formato di visualizzazione , e varia da fornitore a fornitore ma lo sviluppatore Servoy è indipendente da questo .) Ora che conosciamo queste due cose importanti sulle date in Servoy, possiamo vedere la ricerca sulle date. 77 Dobbiamo vedere separatamente due situazioni: quella dove un utente inserisce i criteri di ricerca su una form, e quella dove si programma la ricerca in un metodo . La ricerca delle date per gli utenti Se un utente inizia una ricerca di date e inserisce la data in un campo datetime, Servoy capisce che si deve usando lo stesso formato della data uguale a quello inserito. Così, se inserite 12-05-2005 in un campo configurato con MM-dd-yyyy, sarà interpretato come Dic. 5, 2005 ma se il campo è configurato come dd -MM-yyyy, i dati inseriti saranno interpretati come Maggio 12 , 2005. Se volete essere sicuri, potete specificare il formato desiderato usando il carattere pipe ‘| ' seguito dalla stringa di configurazione. Così si potrebbe scrivere 12-05-2005|MM-dd-yyyy e così costringerebbe Servoy a interpretare il vostro criterio di ricerca come Dic. 5, 2005. Negli esempi sopra esposti, se non si specifica la componente tempo nei criteri di ricerca, Servoy sa che volete la componente tempo ‘azzerata’ e restituirà così i records con il contenuto 12-05-2005 00:00:00. E questo per qualsiasi record, anche per quei record che con data 12-05-2005 contengono la componente tempo diversa da zero. Se l'utente vuole una ricerca su un range di date, egli può inserire 12-05-2005…12-10-2005 oppure 12-05-2005…12-10-2005|MM-dd-yyyy 78 In questo caso, Servoy restituisce tutti i records contenuti nel range dal 12-05-2005 00:00:00.000 al 12-10-2005 23:59:59 Voi potete usare anche i caratteri <, >, = <, >= nei range come criteri di ricerca. Questi sono spiegati in Developer User Guide. Programmare la ricerca delle date in un metodo L'unica cosa che cambia quando voi state programm ando la vostra ricerca in un metodo è che dovete specificare il formato della data con il carattere pipe ’|’. Diciamo che volete ricercare end_date = ’12-05-2005 '. Se il vostro codice è: controller.find() end_date = '12 -05-2005' controller.search() la vostra ricerca fallirà. Per la ricerca codificata voi dovete specificare il formato della data usando il carattere pipe. Così sarebbe corretto: controller.find() end_date = '12 -05-2005|MM-dd-yyyy' controller.search() Date con la componente tempo Se la colonna di datetime che è l'obiettivo della vostra ricerca contiene un valore NON-ZERO nella componente tempo (es. nel caso di una creazione/modifica timestamp), ci sono considerazioni da fare nel caso la ricerca venga eseguita non più su singole date, ma su un intervallo di tempo misurato in secondi. Ad es. se ricercate 12-05-2005|MM-dd-yyyy vuol dire 12-05-2005 00:00:00, e che è il solo valore usato come criterio. Un record che contiene 12-05-2005 11:33:44 non sarà restituito, anche con data valida. 79 Se voi chiedete 12-05-2005…12-06-2005|MM-dd-yyyy che vuol dire dal 12-05-2005 00:00:00 al 12-06-2006 00:00:00, che vanno oltre 24 ore intere del 12-06-2006! Per questo occorre essere accorti. Ci sono alcuni modi per gestire questo. 1. Potete dire ‘non mi interessa il tempo, ma solo la data’, così dovete mettere un carattere ‘#’ all’inizio della vostra stringa di ricerca. Così per cercare #12-15-2005|MM-dd-yyyy restituisce tutti i valori datetime che cadono sul 12-15-2005, per qualsiasi componente di tempo. Anche per cercare queste date #12-15-2005…12-16-2005|MM-dd-yyyy restituisce tutti i valori della componente tempo che cadono dal 12-15-2005 thru 12-16-2005 incluso. 2. Voi potete aggiungere un giorno alla fine del vostro range di ricerca. Se ciò che volete realmente è dal 12-15-2005 al 1216-2005, potreste ottenerlo dicendo 12-05-2005…12-07-2005|MM-dd-yyyy 3. Voi potete sempre farlo in modo più dettagliato in questo modo 12-05-2005 00:00:00..12 -06-2005 23:59:59|MM -ddyyyy HH:mm:ss 80 Consiglio: Uso di campi DATE inv ece di campi DATETIME Se avete bisogno di lavorare solo con le date allora si può considerare di cambiare i campi datetime con solo campi date, supponendo che il vostro db finale lo supporti. In tal caso Servoy lavorerà in modo eccellente con questi campi , ma non sarà necessario dire a Servoy ‘ignora la componente tempo ' poichè non sarà necessario. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 81 Spiegazione dei T abpanels by Adrian McGilly Panoramica sui Tabpanels Una delle più potenti caratteristiche Gui in Servoy sono i tabpanels. Un tabpanel è un'area rettangolare , su di una form, dove visualizzare il contenuto di un’altra form o quello che alcuni chiamerebbero una subform. Ci sono due modi nei quali i tabpanels vengono usati: Visualizzazione di dati correlati Potete mettere molte form nello stesso tabpanel e lasciare che il vostro utente navighi su ognuno di essi . Di seguito (circoscritto in rosso) c’è un esempio del suo uso nella soluzione demo di CRM disponibile sul website di Servoy: [TOP] 82 Ci sono quattro form in questo tabpanel, ciascuna accessibile mediante un proprio tab, e ciascuno dei dati visualizzati è correlato al record del cliente selezionato. Visualizzare i Controlli di Navigazione Potete usare il tabpanel anche come area di una form su cui vengono mostrati tutti i pulsanti di controllo per navigare. Per esempio, potete decidere di mettere lo stesso tipo di controllo della navigazione su tutte le vostre form ma senza duplicare i controlli su ognuna. Creereste solo una form contenente i controlli di navigazione, e poi la mettete dentro un tabpanel su ogni form che ha bisogno di gestire quei controlli. Sotto (circoscritto in rosso) c’è l’esempio di un tabpanel usato per mostrare i controlli di navigazione, della soluzione demo CRM. Notate che non si deve guardare a lui come a un vero tabpanel; perchè non ha i tabs e sui bordi esterni non c'è nulla che riveli la presenza di forms separate al suo interno . Perché un vero tabpanel mostra solo i tabs, ognuno dei quali visualizza ogni form al suo interno . Potete fare in modo che il tabpanel venga incorporato col resto delle form settando opportunamente le proprietà dei suoi contorni . 83 Se avete messo diversi form in un tabpanel, si può scegliere di fare usare all'utente questi tabs per navigare fra i subforms, ma anche di poter programmare la navigazione fra i subforms. Se volete, voi potete rimuovere i tabs e togliere così il controllo all'utente. Questo è quello che noi chiamiamo un tabpanel del tabless. Ciò che è straordinario dei tabpanels è che le forms inserite al loro interno possono contenere delle funzionalità costruit e in loro (es. bottoni per aggiungere, cancellare o andare sui records) e tutte queste funzionalità continueranno a funzionare nel tabpanel. Per esempio diciamo che create una form che deve contenere tutti i controlli per gestire i contatti. Voi potete usarla come una form per gestire standalone i contatti, e potete riusarla in un altro tabpanel correlato alla form delle vostre Aziende clienti e disporre così di un subform per gestire i contatti correlati a ciascuna Azienda. 84 Vi sono tre tipi di tabpanels di cui vogliamo parlare in questa sezione: • Related Tabpanels • Relationless Tabpanels • Tabless Tabpanels Related Tabpanels Forse l'uso più comune per i tabpanels è il tabpanel correlato. Quando voi cliccate sul tool del tabpanel per creare un tabpanel nuovo, Servoy vi chiede a quale relazione volete collegare il subform. Vi presenterà solamente tutte le relazioni esistenti correlate alla tabella sulla quale la vostra form corrente è collegata. Quando cliccate su di una relazione dell'elenco, vi verranno mostrate sulla destra della relazione, tutte le forms collegate ad essa (ciò che chiamo 'destinazione' della relazione nel capitolo sulle Relazioni in questo manuale.) 85 Una volta che scegliete una form da quell’elenco, quella form sarà aggiunta al tabpanel. Sarà rappresentata con un tab all’interno del corpo dell'oggetto tabpanel. Di sotto sono evidenziati i 4-tab dell’oggetto tabpanel dell’esempio (soluzione demo CRM) visti in ambiente di sviluppo. 86 Non dovete confondere le forms inserite nel tabpanel con i tabs ‘position example’ e 'position 2' in alto nel tabpanel. Essi sono in quella posizione solo per illustrare dove i tabs dovranno apparire in modalità run-time. In seguito, chiameremo i tabs che rappresentano le vostre forms form-tabs. Se cliccate una volta sulle form-tabs e guardate all’inizio del pannello delle proprietà, vedrete il nome della relazione alla quale la form-tab è collegata (oppure vedrete 'relationless ' se non è collegata a nessuna relazione). 87 Se fate doppio-click su una form-tab in un oggetto tabpanel (in design mode), Servoy vi porterà alla form rappresentata da quel tab.La relazione a lla quale una form-tab è collegata determina il foundset di records con il quale Servoy popoler à automaticamente il subform quando la soluzione sta girando. Se la relazione per il subform dei contatti è companies_to_contacts , allora ogni volta che la subform viene visualizzata nel tabpanel, Servoy dovrà mostrare tutti i records contatti correlati alla Azienda attualmente selezionata. Leggere questa sezione per conoscere come aggiungere e rimuovere le forms a (da) un oggetto tabpanel esistente. Relationless Tabpanels A volte la form inserita in un tabpanel non è la principale, o almeno non coinvolta in una relazione. Questo può essere il caso per esempio della subform che mostra i controlli della navigazione. In questo caso, quando voi create il tabpanel e Servoy vi chiede a quale 88 relazione i subform dovranno essere collegati, fate un doppio-click su 'Unrelated' e verrà mostrato un elenco di tabelle della vostra soluzione, e sotto a ciascuna di esse, l'elenco di tutte le form collegate. (Se il vostro subform contiene solo un gruppo di tasti di navigazione e nessun dato, poi può sembrare strano che venga chiesto di specificare la tabella della form in modo da arrivare alla form stessa. Pensate semplicemente a questo come unico modo fattibile che ha Servoy di organizzare le vostre form. Ricordate, ogni form è collegata a una tabella, anche se non ne fà uso in alcun modo.) Tabless Tabpanels Un mio studente una volta fece dei commenti relativi alla nozione tabless tabpanel come nozione con tanto senso quanto quello di una fetta di carne senza carne. Sia come sia, è ciò che ottenete quando settate la proprietà tabOrientation di un tabpanel per nasconderlo. Quando fate questo, porta te via il controllo dall'utente togliendo i tabs dal tabpanel, e vi assumete la responsabilità di mostrare la subform solo al momento giusto. Ulteriori spiegazioni su questo tema nella sezione successiva. Come si programmano i Tabs Quando avete aggiunto molte form in un tabpanel, i vostri metodi possono controllare che una di esse venga mostrata nel tabpanel quando lo si decide. Una form con solo campi e bottoni in un tabpanel è semplicemente un altro elemento sulla form. Una sua proprietà è tabIndex. Se settato a 1, mostrerà la prima form. Se messo a 2 mostrerà il secondo, e così via. Nella soluzione demo CRM di Servoy con gli esempi illustrati sopra, la form principale è stata chiamata companies, e il tabpanel è stato chiamato tabs_bottom. Questo il comando per settare il tabpanel in modo che mostri la seconda form, e s. la form che corrisponde al tab 'Addresses' : forms.companies.tabs_bottom.tabIndex = 2 89 Voi potete controllare anche quale tab viene mostrata attualmente con : forms.companies.tabs_bottom.tabIndex Aggiunta/cancellazione di form a/da un tabpanel esistente Per aggiungere un altra form a un tabpanel esistente avete bisogno di selezionare prima l’oggetto tabpanel, cliccando sul tool del tabpanel nella barra degli strumenti . Selezionando prima l’oggetto tabpanel voi comunicate a Servoy di volere aggiungere una form a un tabpanel esistente piuttosto che creare un nuovo oggetto tabpanel. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 90 91 Le Relazioni by Adrian McGilly Panoramica sulle Relazioni Le relazioni sono una delle caratteristiche più potenti e utili di Servoy. Esse vi permettono di dare un nome riconoscibile a tutte le relazioni fra i dati della soluzione, come ‘customers_to_orders’ oppure ‘orders_to_customers’. Dopo avere creato una relazione, potete usarla in molti modi, ma i modi principali sono: • ricerca records correlati • creazione records correlati (con Se rvoy che si prende automaticamente cura della integrità per voi) • cancellazione records correlati • conteggio del numero di records correlati Chiavi Primarie & Chiavi Esterne In qualsiasi relazione tra due tabelle, voi avete una chiave primaria (PK) e una chiave esterna (FK). Considerate una relazione customers-to-orders. Questa è una relazione ‘uno-a-molti’ con il cliente come padre e gli ordini come figli. Ogni cliente ha una colonna come chiave primaria che l'identifica univocamente. Ogni record ordine deve avere una colonna che contiene la chiave primaria del cliente al quale è collegato. Quella colonna viene chiamata chiave esterna. In questo caso, la chiave esterna è un puntatore da un record figlio a un record padre. Origine & Destinazione: Un Modo di Pensare alle Relazioni in Servoy [TOP] 92 Una relazione può andare dal record padre verso i rispettivi records figli, oppure dai records figli verso il padre, questo dipende dalle proprie esigenze. Il box di Definizione della Relazione vi chiede una chiave primari a e una chiave esterna. La chiave primaria è a sinistra, e la chiave esterna è a destra. L'unico problema per questo è che voi creerete delle relazioni che vanno da un record a molti, e altre che vanno da molti records a uno, ma nel secondo caso, la chiave sulla sinistra in realtà sarà la chiave esterna, e la chiave sulla destra sarà la chiave primaria che è l'opposto di ciò che il dialog di Definizione della Relazione vi sta chiedendo. Invece di pensare in termini di chiavi primarie e chiavi esterne, preferisco pensare in termini di chiavi di record origine e destinazione. Se volete una relazione che contiene gli ordini di un cliente dovete andare dal rec cliente verso i suoi rec ordini. Se volete una relazione che vi darà il cliente di un determinato ordine dovete andare dall'ordine al cliente. La vostra origine ‘è ciò che voi già avete’, la destinazione è ‘ciò di cui avete bisogno’. L’origine và sulla sinistra, la destinazione va sulla destra. Fine della confusione. Relazioni Uno-a-Molti Se volete una relazione per ricercare, aggiungere, cancellare, contare tutti gli ordini di un dato cliente, dovrete inserire: 93 Per default Servoy nomina questa relazione customers_to_orders che collega fra loro le tabelle. Di solito non c’è il bisogno di modificare il nome presentato per default , ma se volete potete farlo. Potete fare uso di una delle caratteristiche più potenti di Servoy: il tabpanel correlato. Potete creare un tabpanel per visualizzare / modificare / aggiungere gli ordini collegati a un cliente. Quando aggiungerete nuovi ordini in questo tabpanel Servoy si prender à cura della integrità di tutti i dati che sono tra di loro collegati. Per fare questo avete bisogno di una form (chiamiamola ordersForm) collegata alla tabella ordini , che contenga quegli ordini che volete mostrare nel vostro tabpanel (presumiamo per il momento di stare trattando solo le testate dell'ordine e non le righe dell'ordine). Una volta fatto, potete creare un tabpanel sulla form del cliente, collegata alla relazione customers_to_orders, selezionate la 94 ordersForm e fatto! Ogni volta che l’utente seleziona un cliente sulla form principale, Servoy automaticamente ricerca e mostra tutti gli ordini del corrente cliente nel tabpanel. Ora poniamo di inserire un tasto ‘Add’sul ordersForm il cui metodo dice controller.newRecord() Se l'utente clicca su quel tasto Servoy saprà- perché sta usando la form del tabpanel customers_to_orders -che si vuole creare un nuovo record ordine che punti al (es. con la chiave esterna) PK del corrente record cliente, e di conseguenza lo crea. Così come spiegato nella sezione Lettura, Aggiunta & Cancellazione Records Correlati è lo stesso che dire customers_to_orders.newRecord(). Relazioni Molti-a-Uno Al contrario, se volete una relazione che vi fornisca il cliente per un dato ordine, dovrete inserire: 95 Per default Servoy nominerà la relazione orders_to_customers. Ora, se voleste mostrare in un campo il cognome del cliente al quale appartiene l'ordine selezionato, specifica te nella proprietà dataprovider del campo: orders_to_customers.last_name Vedrete che l'IDE di Servoy vi farà accedere al momento giusto alla giusta relazione. Ad esempio se aggiungete un nuovo campo alla form Ordini (es. una form collegata agli ordini), il dialog che vi lascia scegliere il dataprovider per il vostro campo lo farà selezionare dalla relazione orders_to_customers e vi darà così accesso al dataproviders del cliente correlato. Relazioni Molti-a-Molti Non è immediatamente facile comprendere come creare una 96 relazione molti-a-molti. Jan Aleman, CEO of Servoy, scrisse un articolo su questo che potete vedere sul Periodico di Servoy: http://www.servoymagazine.com/home/2004/10/article_nm_rela. html Relazioni nominate da voi Potete definire voi stessi i nomi di relazione, per esempio riflettere l’albero gerarchico degli impiegati e dei loro supervisori. Questa relazione vuole ottenere tutti i consulenti che dipendono da un consulente supervisore: In questo caso sarebbe utile cambiare il nome della relazione con qualche cosa di più significativo come consultants_to_reports . Sappiamo che se decidete di cambiare il nome di una relazione, questo comporta la rottura di tutti quei riferimenti già esistenti nel vostro codice JavaScript. Questo non vale invece per tutti quei 97 luoghi dove la relazione viene usata, come ad esempio nella proprietà ‘dataprovider’ del pan nello delle proprietà, oppure quando viene specificata all’interno di un tabpanel, in tutti questi casi Servoy 'rinomina' que lla relazione per voi. Leggere questa sezione per informazioni sulle riparazioni ai metodi che hanno subito il cambiamento al nome di un oggetto. Relazioni Globali Infine, potete creare relazioni globali, dove sul lato sinistro del nome invece di un record c’è il nome di una var globale. Ciò può essere utile in situazioni dove si devono recuperare records correlati, ma si dispone solamente del valore della chiave PK del record padre, ma non del percorso nel foundset. Di seguito vi è l’esempio di una relazione che trova i progetti di un cliente la cui chiave PK è contenuta in un campo globale globals.clientID: 98 Relazioni Nidificate Si possono concatenare insieme delle relazioni per arrivare al dataprovider correlato per un campo , come questo: relation1.relation2.relation3.dataprovider Per esempio, se da un record della tabella order_items volete ottenere il cognome del cliente correlato, dovete fare così : orderitems_to_orders.orders_to_customers.last_name Se state scrivendo un metodo per una form collegata alla tabella customer e desiderate inserire un campo co ntenente come dataprovider un elemento orderitems 'HB1550' di un ordine, dovrete dire: customer_to_orders.orders_to_orderitems.part_no = 'HB1550' Bene, ma quale record orderitems è riguardato da questo comando? È 'la riga selezionata di un ordine seleziona to del cliente selezionato'. E come facciamo a selezionare tutti questi records? Il modo migliore per rispondere è di guardare a un esempio. Diciamo che invece di assegnare l’elemento 'HB1550' di un ordine, si vuole fare un loop su tutti gli ordini di un dato cliente per vedere se il cliente abbia mai ordinato l’elemento #HB1550, si dovrebbe fare: /* configurazione di un for loop attraverso tutti i records ordini del cliente corrente */ for (var n = 1; n <= customer_to_orders.getSize(); n++) { /* selezione del record orders dal foundset o orders correlato*/ customer_to_orders.setSelectedIndex(o); 99 /* set up di un for loop attraverso tutti gli elementi dell’ordine selezionato */ for (var m = 1; m <= customer_to_orders.orders_to_orderitems.getSize(); m++) . { /* selezione de l record orderitems dal foundset o orderitems correlato */ customer_to_orders.orders_to_orderitems.setSelectedIn dex(m); if (customer_to_orders.orders_to_orderitems.part_no == 'HB1550') { return true; } } } return false; Lettura, aggiunta & ca ncellazione di record correlati Guardiamo ad altri esempi di ciò che si può fare con le relazioni. Questi esempi presumono di scrivere un metodo del form clienti collegato alla tabella customer: // seleziona tutti gli ordini correlati al cliente scelto customers_to_orders.setSelectedIndex(n) // aggiunge un nuovo record orders correlato al customer scelto customers_to_orders.newRecord() /*aggiunge un nuovo record order_items al record orders selezionato correlato al cliente selezionato */ customers_to_ orders.orders_to_orderitems.newRecord() 100 // cancella il record orders selezionato e correlato al cliente scelto customers_to_orders.deleteRecord() // vi dice quanti rec orders ci sono per quel cliente selezionato customers_to_orders.getSize() Riassumendo le Relazioni Ricapitolando. Se volete una relazione che vada dal rec padre a ogni rec figlio (es. parent_to_child), allora settate il box di Definizione Relazioni così: Parte sx (source) Parte dx (destination) Tabella parent table child table Dataprovider parent.pk child.fk Se volete una relazione che vada da ogni rec figlio a ogni rec padre (es. parent_to_child), allora dovete fare: Parte sx (source) Parte dx (destination) Tabella child table parent table Dataprovider child.fk parent.pk Opzioni di Relazione Two options appear at the bottom of the relation dialog • Permette la creazione dei records correlati 101 • Cancellazione dei records correlati Di seguito la loro spiegazione Permette la creazione dei records correlati Nel nostro esempio di customers_to_orders, il comando ‘customers_to_orders.newRecord()’ crea un record ordine correlato al record del cliente selezionato , ma solamente se l’opzione corrispondente viene settata , altrimenti darà un errore. Egualmente, Cancellazione dei records correlati Così come Servoy si prende cura della integrità dei riferimenti quando si aggiungono records correlati tramite una relazione (es. customers_to_orders.newRecord ()), così come assicura la loro integrità quando si cancella un record padre. Se settata, allora quando un metodo o un utente cancellano il record di una tabella del lato sinistro della relazione, allora tutti i records correlati della tabella nella parte destra della relazione saranno cancellati. Questa è una scelta abbastanza potente – che occorre usare con attenzione. by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 102 103 104 105 Consigli e Convenzioni sulla Programmazione by Adrian McGilly Stabilire convenzioni sui nomi e attenersi a esse Nella vostra codifica in Servoy si assegnano molte entità diverse fra loro, all’interno dei: forms (alcuni dei quali dovranno apparire solo nei tabpanels, e nei subforms più che forms) • dataproviders • elements • relations • global vars • local vars • calcs • global methods • form methods L’utilizzo di una convenzione sui nomi vi aiuterà nella vostra organizzazione. Per esempio, se non siete accorti, si potrebbe finire con l’avere un dataprovider chiamato last_name che risiede in un campo chiamato last_name, e una var locale chiamata last_name. Si otterrebbe cos ì una grande confusione. Occorre anche sapere che tutti questi nomi sono cas e sensitive. Non è la stessa cosa dire customerForm e CustomerForm. Così non si possono usare i nomi mescolati, ma occorre mantenerli uguali. [TOP] 106 Una regola base per molti sviluppatori Servoy stà nell’usare una distinzione, ad es. tra nomi di dataprovider e i nomi di variabili usando tutte lettere minuscole e underscores ‘_’ per i dataproviders (es. last_name) e quelle chiamate ‘camel case’ per le variabili (es. lastName o globals.lastName). Ci sono dei buoni articoli scritti sulla convenzione dei nomi in Servoy Magazine –questo è il link: http://www.servoymagazine.com/home/2005/04/tip_organizatio .html. Raccomando la lettura di questi articoli prima di addentrarsi in qualsiasi soluzione che si intende distribuire e manutenzionare. Se si rinomina qualsiasi oggetto dopo averlo già adoperato nel proprio codice, si compromettono i metodi che contengono i vecchi riferimenti. Una sezione seguente spiega come si possono riparare quei metodi che hanno subito la rinominazione di oggetti. Cliccare e non scrivere! L' oggetto albero in Servoy Editor è molto in telligente nella gestione degli errori di scrittura del codice. Quando fate doppio click su una funzione o su una proprietà o dataprovider nell'albero, questo muove il riferimento scelto nel vostro codice. Ciò che non si può sapere prima è se il metodo ch e si sta prelevando è un metodo di form o un metodo globale, e se è un metodo della form, a quale form appartenga. Così ad esempio, se lavorate in un metodo della form che appartiene alla customerForm, e fate doppio-click su un dataprovider chiamato last_name sotto il nodo del selectedRecord di quella form, inserite last_name nel vostro metodo. Ma, se state lavorando in un metodo globale (o un metodo che appartiene a una diversa form), Servoy sa che vi deve proporre di inserire precisamente nel vostro codice la stringa completa ‘forms.customerForm.last_name’ . 107 Per molte funzioni della libreria potete muovere una parte di codice di esempio dentro il vostro metodo cliccando sul tasto ‘move sample’ nel Servoy Editor –questo vi fà risparmiare molto tempo. Quando muovete il vostro mouse su una proprietà o su una funzione, la sua descrizione e sintassi appaiono brevemente con un tooltip e inoltre appaiono anche nella sbarra di stato in basso fino a quando muovete via il mouse . Usare application.output() per vedere 'cosa sta girando' Quando si comincia a giocare con la scrittura dei metodi, si troverà utile sbirciare i valori d i variabili, dataproviders e valutare le espressioni al volo. Mentre il debugger offre un buon aiuto in questa area, spesso trovo più utile ‘visualizzare’ queste cose sul pannello di output del debugger utilizzando application.output() . Di seguito alcuni esempi: Command Output (visibile nel pannello output del debugger) application.output('Hello World') Hello World application.output('Hello' + 'World') HelloWorld application.output('last_name = ' + last_name) last_name = Smith application.output('qty * price = ' + qty * price) qty * price = 270 108 Dichiarazione di vars globali nella finestra dataproviders JavaScript permette di dichiarare var globali nei metodi, ma queste non sono aggiunte automaticamente all'elenco di globals nella finestra dataproviders. Cosa che potrebbe portare disordine se si prolifica in dichiarazioni di var globali in tutto il vostro codice, per cui è da evitare. Se le dichiarate tutte in un metodo centrale dove si possono vedere tutte, sarebbe OK, ma è preferibile dichiararle direttamente nella finestra dataproviders. Usare Ctrl-spacebar per velocizzare la codifica In codifica se si decide di scrivere piuttosto che cliccare, c'è ancora un altro tool nel Servoy Editor che può aiutare, ed è il comando control-barra spaziatura. Provare a scrivere ‘forms.’ in un metodo e poi premere control- barra spaziatura (command-spacebar su Mac). Servoy presenta un elenco delle form presenti nella vostra soluzione. Poi si può scegliere una form col click del mouse o scorrendo la lista con la tastiera e premendo il tasto invio. Servoy si muove al successivo livello nell'oggetto albero e vi offre tutti i nodi sotto il nodo form. Farà questo fino alla fine dell'albero.Buono! Essere consapevoli del case-sensitivity Ricordate che tutti i nomi di tutti gli oggetti, funzioni , metodi, classi, dataproviders, tabelle, variabili ecc. sono case sensitive in JavaScript. Una chiamat a al forms.customerForm.Validate() non è la stessa del forms.CustomerForm.validate() e se non siete accorti, potete passare molto tempo sul codice JavaScript che genera errori di programmazione, e non vede re che il problema può essere una semplice questione di una let tera maiuscola, o viceversa. Questa è un’altra buona ragione per cliccare invece di scrivere. 109 Settaggio delle proprietà a tempo di esecuzione Si possono controllare dinamicamente molte proprietà della vostra soluzione durante la sua esecuzione settandole direttamente nei metodi. Ad esempio potete fare apparire i campi, nasconderli, renderli modificabili o no, abilitare o disabilitare intere form, ecc. Questo è spiegato nella Developer’s User Guide. Non tutte le proprietà che si vedono nel pannello delle proprietà sono modificabili a tempo di esecuzione. Le proprietà che si possono cambiare a programma per qualsiasi oggetto sono elencate nel Servoy Editor ogni volta che si clicca su un elemento dell' oggetto albero. Quando cambiate in run-time una proprietà, la modifica persiste solamente fino a quando l'utente chiude la soluzione, e poi quella proprietà ritorna al suo stato originale. In ambiente di sviluppo se uscite dal run-time mode e andate in design mode, tutte le proprietà prima modificate sono riconvertite ai loro valori originali. Usare calcs non-memorizzati per checkboxes Poniamo di voler presentare a un utente un elenco di records clienti e lasciare che selezioni quello che vuole includere in un processo (es. un report). Un modo sarebbe quello di mettere un checkbox come campo del cliente e lasciare che l'utente scelga quello che desidera. Come si fà questo? Potete anche creare una colonna boolean nella tabella customer, ma per questo occorre dedicare dello spazio su disco per una colonna di cui non avete necessità di salvare, e inoltre dovete preoccuparvi del flag quando viene salvato con lo stato in ‘on’. Questo vi costringe a inizializzare sempre questi flags a false prima di esporli come checkboxes. La risposta è quella di creare un calc non memorizzato di tipo 110 integer nella tabella customer e settare nothing a ’all’, e con solo il comando return nello script. Poi inserite nel calc il dataprovider per il vostro checkbox e siete pronti per lavorare. Quando il vostro utente seleziona un elemento del checkbox nell'elenco (es. foundset) dei clienti, il calc per quella riga del foundset sarà posto a 1. Per le righe non settate sarà posto a 0. Inoltre conserverà il suo valore di 1 finchè il foundset rimane in memoria. Se create un nuovo foundset, i calcs devono essere tutti resettati a zero, e ciò consentirà a tutti i checkboxes collegati al calc di risultare non selezionati. Contenitori che non persistono alla uscita da modalità run-time In Servoy Deve loper, se si entra e si esce dalla modalità run time mentre siete in debug, ricordate che nessun dataproviders o variabile globale, può persistere una volta che si esce da modalità run-time. Questi oggetti ritornano al loro valore originale che, a meno che non sia specificato diversamente, è zero o vuoto (dipende dal tipo di var). Fare spesso il Back up delle soluzioni Ricordate, tutto il disegno delle vostre soluzioni e il lavoro di programmazione è nel database servoy_repository.db. Se il repository si corrompe o in qualche modo viene cancellato, voi perdete tutte le soluzioni ivi contenute. Sebbene SQL Anywhere sia molto stabile, è meglio non correre il rischio di perdere tutto il vostro lavoro . Occorre fare frequenti backups del vostro repository, e se possibile, della vostra intera cartella database. Uso dell’ help L’ help presente sotto il menu di help è la stessa versione dello stesso documento PDF di carta della guida di riferimento, solo il tool di ricerca è diverso. Dopo avere compiuto una ricer ca 111 iniziale con il tab Ricerca per chiave, mostrerà un elenco contenente le parole cercate. Per andare poi sulla pagina di un tema specifico si deve selezionare Tools>> Find e cercare di nuovo per chiave. Global find & replace correzione dopo rinomina oggetto Se cambiate il nome di un oggetto che è referenziato nei vostri metodi (es. una form, una relazione, un dataprovider ecc.) si può compromette il loro funzionamento. Potete usare il comando global find & replace che è sotto Edit>>Find nell’Editor di Servoy per cercare le referenze al vecchio nome e sostituirle col nuovo. Tasti chiave per andare in Servoy Editor Con Ctrl-Shift-M si ottiene di passare dalla finestra di design al Servoy Editor. Questo, sia in design mode sia che la soluzione stia girando. Se volete modificare un metodo collegato a un evento nel pannello delle proprietà, tenete premuto il tasto Ctrl con doppio-click sul nome del metodo nel pannello della proprietà questo aprirà quel metodo in Servoy Editor. Un altro consiglio, dopo aver fatto modifiche a un metodo, premendo Ctrl-S il metodo verrà verificato e se non verrà trovato alcun errore il metodo verrà salvato. Questo risulta più rapido che fare i passi separati di verifica e salva. by Adrian McGilly, Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] Non dimenticare il doppio == nel comando if! Ricordate che in JavaScript, per esaminare l’uguaglianza bisogna usare due segni di uguale. Non fate così: 112 if (i = j) /* assigns the value of j to i and returns the value of i to your if test */ {… } ma così: if (i == j) // uses two equal si gns to test if i equals j {… } Questo può essere un grave errore inserito nel codice, annotate! Selezionare righe di codice & formattarle in un colpo Se volete formattare i margini di una parte di righe di codice in un metodo, selezionate le righe che volete formattare e colpite il tab – Servoy inserirà una tabulazione a fronte di ogni riga selezionata. Non c’è modo di chiedere all’editor una “particolare” formattazione delle righe di codice con i rientri coerenti al formato. In Editor non usare alcune k eywords nei commenti Nella versione 2.2.5 si possono generare alcuni errori quando si tenta di salvare un metodo se vengono trovate parole riservate JavaScript nei commenti. Se per esempio ottenete la segnalazione ‘parola chiave function trovata in questo script’potrebbe essere solo stato trovato ‘function’ in qualche commento. (Sì, l’editor non digerisce la vista di parole riservate inserite nei commenti). Voi dovrete trovare un modo diverso di esprimerle. Esiste un elenco di parole riservate nell'Appendi ce di Developer's Reference Guide. Nella programmazione i Colori fanno stranezze Servoy Editor quando codifica i colori nel vostro codice, non 113 sempre ottiene l’effetto giusto. Per esempio potrebbe inserire la parola ‘for’ come un commento. Non prestate par ticolare attenzione – è solo estetica e non riguarda le vostre funzionalità. Lasciate Generare i Timestamps a Servoy Avete bisogno di registrare il timestamp di creazione/modifica per alcune tabelle? Servoy può farlo automaticamente. Occorre creare due colonne per timestamps per la creazione e la modifica del record e poi andare selezionare la colonna nella finestra del dataproviders e cliccare sul tasto delle Proprietà. Saranno mostrate le due proprietà di Creazione Timestamp e Modifica Timestamp. Selezionare la proprietà corrispondente ed è fatto! by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 114 Debugger Consigli e Suggerimenti by Adrian McGilly Servoy possiede un grande debugger. È documentato bene nella Developer User’s Guide, ma qui ci sono un paio di consigli per chi inizia: La soluzione deve “girare” per poter fare uso del debugger Anche se può sembrare ovvio, lo dirò lo stesso. Non potete fare girare un metodo o avanzare attraverso i suoi step se la soluzione è in design mode. Se siete in ‘design’ mode allora premete ctrl-L per comandare l’apertura della form corrente in run-time, e quindi attivare il debugger. Modifica dei metodi mentre la soluzione sta girando Potete editare i metodi mentre la vostra soluzione è aperta in 'run-time'. L'unica eccezione che ho trovato è quando si ha il debugger attivo e l’esecuzione è stata intercettata da un punto d'arresto, allora non viene permessa nessuna editazione dei metodi fino alla chiusura del debug, ad es. premendo il tasto verde che completa l’esecuzione e chiude il debug. Potete lanciare un metodo direttamente dal debugger Colpendo il tasto verde ‘play’ si otterrà il lancio del metodo attualmente mostrato. Questo è più veloce che predisporre un tasto su una form per esaminare un metodo. Visionare le variabili In Servoy Editor il tab delle variabili serve solo per guardare argomenti, vars locali e oggetti java. Non sono permesse vars globali. Per le vars globali occorre usare il tab Wath. Alcuni hanno avuto difficoltà nel capire l’uso di questi tab, così spesso da fare uso del comando application.output () per [TOP] 115 vedere il contenuto delle vars globali. Il tab Evaluate serve per valutare espressioni al volo, oppure per cambiare il valore di vars local i. Pulire il pannello di output Se il pannello del tab di Output appare pieno e si desidera pulirlo, cliccare col tasto destro del mouse nel pannello che vi presenterà la possibilità di pulirlo . Comportamento del debbugger con showFormInDialog Se state usando il debugger per avanzare all’interno di un metodo che possiede un comando showFormInDialog, otterrete uno strano comportamento del debugger quando vi mostrerà il relativo box dialog . Se il comando showFormInDialog() viene richiamato in un punto , allora il sistema suppone uno stop di esecuzione de l metodo fino a quando la finestra del dialog verrà CHIUSA. Se state avanzando attraverso il metodo richiamato, rimarrà in quel punto sospeso, e potrebbe procurarvi confusione. Se fate debugger in un metodo con un showFormInDialog () richiamato, cercate di evitare di usare il tasto step e usate invece use application.output() . by Adrian McGilly, Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] 116 Appendice by Adrian McGilly Creazione di una Tabella con 500 record s Questa sezione vi mostra il processo per inserire 500 records in una nuova tabella con Servoy. Ciò è utile per imparare a navigare nei foundsets, come discusso nella sezione sui foundsets. 1. 2. Create un nuovo form chiamato FoundsetFun. Quando presenta il dialog, chiamate il form companiesForm e lo collegate al server database user_data, e a una nuova tabella chiamata companies. Il dialog dovrebbe essere: [TOP] 117 3. 4. 5. Premete OK. Questo vi porterà alla Finestra del Dataproviders dove definirete le colonne per la tabella companies. Per ora, abbiamo appena due colonne: la colonna chiave primaria companiesid generata da Servoy, e la colonna che voi aggiungerete chiamata name, di tipo testo e con lunghezza 100. La finestra del Dataproviders dovrebbe essere così: Un click su Apply, e poi un click su OK. Ora Servoy creer à la nuova form, e mostrerà un dialog 'Specify Field(s)' dove selezionare i campi da mostrare sulla form. Selezionate entrambi i campi nell'elenco e settate 'Place labels' nel checkbox. Il vostro dialog dovrebbe essere così : 118 6. 7. Premete OK. Ora andiamo in run-time mode con ctrl-L dovreste vedere il controllo di navigazione sulla parte sinistra della finestra, con zero record mostrati: 119 8. Ora andiamo in Servoy Editor con Tools>> Editor. Vedrete il companiesForm già selezionato nell'oggetto albero, e nel pannello sotto l'albero un piccolo tasto verde per la creazione di un nuovo metodo (vede re sotto). Cliccare sul tasto per creare un nuovo metodo. 120 9. Chiamare il metodo 'create500', e inserire il seguente codice nel pannello di edit dei metodi: for (var i = 1; i <=500; i++) { controller.newRecord(); name = 'Company ' + i; } Questo metodo crea 500 records nella tabella companies, e ogni colonna name per ogni record sarà 'Company 1', 121 'Company 2', 'Company 3', etc. 10. Il vostro metodo dovrebbe essere come illustrato sotto. Ora cliccate sul tasto Verify per verificare e salvare il metodo, e se non risultano errori, allora cliccate sul tasto verde "play" per eseguire il metodo. 11. Attendere mentre Servoy crea i 500 records nella tabella companies. Ogni azienda sarà chiamata 'Company 1', 'Company 2', 'Company 3', ecc. Vi prenderà circa da 1 a 20 secondi a seconda della potenza della vostra macchina. Saprete che ha finito quando tutti i tasti del debugger sono ritornati allo stato inattivo come illustr ato sopra. 12. Tornate al vostro form in run -time mode, e vedrete che ora avete 500 records nella vostra tabella: 122 by Adrian McGilly , Servoy Consultant & Trainer Copyright 2006, All Rights Reserved [TOP] Questo documento è stato prodotto da Metamorfosi in proprio. La Casa Madre Servoy Consultant & Trainer che detiene i diritti sui documenti in lingua originale non si assume alcuna responsabilità sui contenuti di questo documento nè di eventuali errori e omissioni. Rev. Data Rev. Data 1° Pubblicazione Scritto da: Prodotto da: 0 4/9/2006 4/9/2006 Michele Annese Metamorfosi 123