Lo scorso anno verso fine estate qualcuno mi ha chiesto di pubblicare gli itinerari che avevo percorso nelle precedenti settimane attraverso le montagne del Cadore, della Val Zoldana e della Val Pusteria. Complici la ripresa delle attività invernali, e vari impegni, alla fine non ho più fatto nulla e questi piacevoli camminate sono cadute un po’ nell’oblio, rimanendo poco più di un bel ricordo nella mia testa. Quest’anno, mentre si avvicina la data ufficiale della riapertura estiva dei rifugi, ho deciso di provare ad impegnarmi a parlarvi più dettagliatamente di queste mie scorribande tra cengie e bivacchi, pubblicando assieme ai dettagli di ogni escursione anche qualche foto e le mie impressioni. Sabato 3 Giugno ho deciso di affrontare la salita ad un rifugio che tipicamente è già in attività quando gli altri ancora non hanno aperto la stagione, tanto è vero che anche nel periodo primaverile, in occasione di alcuni weekend il rifugio apre i battenti e offre l’occasione di raggiungerlo magari muniti di ciaspe e assaporare le piacevoli pietanze preparate dalla moglie del gestore.

Il Rifugio Alpino Dino e Giovanni Chiggiato, si trova nella parte iniziale del Cadore, poco lontano da Calazo di Cadore, per chi proviene dalla pianura e questo è un vantaggio indiscutibile rispetto ai più blasonati rifugi dolomitici perchè è possibile raggiungerlo in giornata, anche nei giorni di maggiore frequenza, senza rischiare di fare ore e ore di coda al rientro, dato che è molto meno distante da Longarone e dall’autostrada rispetto a molti altri. Tuttavia aspettatevi comunque un po’ di coda se lo raggiungete nelle giornate più critiche come la Domenica. Quest’anno l’ho scelto come “apripista”, un po per allenare il fiato, un po’ perchè dopo averlo visitato l’anno scorso mi è rimasto impresso per la bellezza del paesaggio nel quale è collocato oltre che per la cura con cui il gestore ne conserva la struttura (Premiato nel 2015 come miglior Rifugio del Cadore). Negli anni scorsi lo avevo sempre un po’ snobbato per un errore di valutazione, complice l’altitudine non troppo elevata (1911 m.s.l.m) e il fatto che sia pubblicizzato da cartelloni all’uscita dell’autostrada, avevo erroneamente pensato si trattasse di un luogo eccessivamente frequentato dal peggiore turismo, ma in realtà ho scoperto in esso un punto da raggiungere spesso per passare una giornata immersi nella tranquillità ricavata tra alcune delle più belle cime delle Dolomiti.

imageQuest’anno ho scelto la salita più classica, il sentiero che parte dalla località “La Stua” (segnavia 261) e risale la montagna con una pendenza pressoche invariata dall’inizio alla fine. In effetti trattandosi del sentiero più battutto, costituito in gran parte da una stretta stradina ben segnata e curata – diversamente dai sentieri dei rifugi più importanti che spesso sono irti e costellati da continui sassi e radici che ostacolano il passo – si può essere portati a pensare che sia facile. In realtà, le 2 ore nominali di questo percorso si rivelano un impegno atletico “importante” dato che il sentiero non vi darà tregua, richiedendovi minuto dopo minuto di attingere a tutta l’energia che avete nelle vostre gambe per arrivare alla agognata destinazione.

La partenza del sentiero è situata in località “La Stua”, raggiungibile in macchina, mantenendo la destra dopo il ponticello che si trova poco dopo la Chiesetta del Caravaggio in direzione “Praciadelan” a Calalzo di Cadore (BL). Occorre fare un po’ di attenzione perchè dopo il ponte vi si presenta una casa nel bel mezzo del bivio ma la strada che dovrete imboccare, ad un occhio poco esperto, può apparire come il viottolo che conduce al retro. Invece, superata la casa vi troverete su una stretta stradina asfaltata ma piuttosto dissestata che sale per circa 2 km in mezzo alla montagna, a ridosso del torrente. Molta attenzione dovranno porla quelli che sono dotati di una vettura bassa perchè le frequenti buche li porteranno spesso a “grattare” se non procederanno con cautela. Al termine, si arriva in un piccolo parcheggio che può ospitare almeno una decina di vetture e indossati degli adeguati scarponi e uno zainetto con un kit precauzionale da montagna si inizia la salita sulla restante parte della strada asfaltata inaccessibile alle vetture.

WP_20170603_11_13_00_Raw_LI__highresLa strada assume quasi immediatamente una pendenza costante che la caratterizzerà per tutto il tortuoso percorso, aumentando gradualmente anche per effetto della stanchezza che mano a mano si accumula. Dopo aver abbandonato l’asfalto il sentiero si tramuta in una pastorale piuttosto larga e segnata dagli alti alberi che la tengono costantemente in ombra. Se la giornata non è delle più calde sarà opportuno indossare un golfino leggero per proteggersi dall’umidità del bosco. Mano a mano che si sale, si incontrano numerose deviazioni dal sentiero principale, alcune di queste sono poco più che scorciatoie che usualmente consiglio di evitare perchè, pur sembrando un’ottima idea a prima vista, alla fine logorano le nostre energie molto più velocemente del percorso più lungo ma più dolce. Il sentiero è sempre e costantemente segnato da numerosi segni rossi e bianchi, alcuni riportanti il numero 261 ben evidente. E’ davvero impossibile perdersi, anche grazie a una buona quantità - quasi eccessiva - di indicazioni per il rifugio, giustficate WP_20170603_11_46_04_Raw_LI__highresdal fatto che nel periodo invernale segnano il sentiero dedicato alle ciaspole. Vista l’altitudine non eccessiva, la vegetazione rimane sempre molto rigogliosa garantendo una frescura per tutto il percorso e aprendosi solo per un breve tratto quando si giunge a circa venti minuti dal rifugio. In questo tratto finale i più fortunati potranno ammirare un buon numero di camosci intenti a brucare in un pendio scosceso poco distante dal sentiero. Sarete facilmente attirati dal rumore legnoso che rompe il silenzio quando le corna dei maschi si incrociano in brevi scambi incruenti. Continuando a camminare sulla salita che oramai è alla sua più impegnativa pendenza finalmente si intravvederà la bandiera che segna il punto più alto in prossimità del fabbricato in pietra corrisponente al rifugio. Questo in effetti è il primo punto che si raggiunge quando la vegetazione lascia spazio allo sguardo e, prima ancora di notare il rifugio una cinquantina di metri più sotto, sarete sicuramente rapiti dal panorama fantastico che include sulla sinistra gli Spalti di toro, più al centro l’Antelao e infine le Marmarole, in una parata che trova validi rivali sono in alcuno dei più alti e impegnativi rifugio dell’alto Cadore e del Tirolo del Sud.

WP_20170603_13_51_35_Panorama







Questo punto, dotato di due tronchi di legno trasformati in panchine è di certo uno dei migliori per fermarsi prima di raggiungere il rifugio, e il prato molto ampio vi consentirà anche di godere il meritato riposo sentendo il sole di montagna scaldarvi la pelle mentre il profumo dell’erba vi rilassa le narici. Poi, dopo aver ammirato a lungo il panorama punteggiato nel basso dalla città di Calalzo e da un ampio scorcio del lago Centro Cadore, è d’obbligo recarsi al rifugio e godere delle ottime pietanze che le sapienti mani della cuoca sapranno confezionare. Potrete gustarle nella tettoia all’esterno oppure in una bellissima sala da pranzo dotata di tavoli e rivestimento in accogliente legno.

WP_20170603_15_22_48_Panorama

Cerco sempre di protrarre a lungo la mia permanenza in questo luogo meraviglioso, magari leggendo un libro o chiacchierando mentre sorseggio una birra. Tuttavia alla fine giunge il momento di tornare. al ritorno il sentiero è nuovamente impegnativo perchè la sua pendenza insiste sulle ginocchia senza troppa pietà, ma la discesa è molto più breve e agevole della salita, e se non fosse per la pioggerella che stavolta ha bagnato l’ultimo quarto d’ora, la giornata si sarebbe potuta dire ampiamente perfetta. Ora è il momento di pensare alla prossima escursione… mi attente il Rifugio Tita Barba fra un paio di settimane all’apertura ufficiale della stagione.

Informazioni WP_20170603_14_11_21_Raw_LI__highres

  • Destinazione: Rifugio Alpino Dino e Giovanni Chiggiato (CAI Venezia)
  • Data escursione: Sabato 3 Giugno 2017
  • Posizione: Marmarole Centrali (mappa)
  • Durata: poco più di 2 ore per gambe allenate, fino a 2:45 per i meno preparati.
  • Apertura: Continuata da metà Giugno a fine Settembre e nei weekend di bel tempo per il resto.
  • Difficoltà: Facile il percorso ben segnato ma richiede buona resistenza fisica e costanza nel passo.
  • Sentiero: 261 da Località La Stua (Calalzo di Cadore – BL)
  • Telefono: +39.329.0757808 - +39.346.1817182


Nella foto il simpatico cane del gestore mentre custodisce la mia birra…

tags: - categories:

20160324032017Vi hanno mai detto che "violenza genera violenza"? Pensateci voi che esprimete violenza su Facebook, che condividete e fate vostro, il pensiero violento di un tiranno come Putin. Pensateci voi che magari siete stati cresciuti nell'insegnamento cristiano del "porgi l'altra guancia", senza comprenderne il significato.

Io negli atti di Bruxelles, nelle violenze terroriste, leggo l'invidia. L'invidia per un sistema tutto sommato civile che tutela - entro i limiti dell'umana fallibilità - l'essere umano ed i suoi diritti, contrapposto alla povertà, all'ingiustizia e alla sofferenza che vivono certi popoli.

Questo dovremmo avere sempre a mente e questo dovrebbe rivelarci chiara la strada per porre fine al terrorismo, alle violenza, alla guerra. "Non c'è pace senza giustizia, non c'è giustizia senza il perdono" ha detto Karol Wojtyla, il Papa di cui molti hanno richiesto la santificazione ma di cui tutti scordano gli insegnamenti... 

E oggi è il momento di essere forti nel perdonare, forti nel ristabilire la giustizia e soprattutto forti nel riconoscere i propri peccati... i peccati di una società, la nostra, che assorbe la ricchezza del mondo anzichè distribuirla, una società che è, essa stessa, alla base dell'ingiustizia che assieme all'ignoranza è terreno fertile per atti di violenza.

Non sono bombe quelle che voglio vedere sganciate sui cittadini inermi, sugli sfortunati che sono esclusi dal benessere della civiltà occidentale... Per una volta, invece che riversare esplosivi, sganciamo ricchezza, istruzione, benessere e cultura. Accogliamo queste popolazioni, facciamo loro vedere la nostra cultura, le arti, le scienze e ascoltiamo le loro... diamogli le opportunità che abbiamo noi, rischiando così anche di perdere una parte delle nostre prerogative. Ne uscirà una eguaglianza sociale, una amalgama di usi e costumi che ci renderà finalmente un solo popolo sulla terra. Noi occidentali, noi europei, noi fortunati, non siamo per forza dalla parte giusta!

Facciamo giustizia... la pace verrà...


Pere al cioccolato è la prima cosa che m'è venuta in mente... Quegli squisiti frutti che divoravo cogliendoli direttamente dalla pianta nelle campagne del Cilento dove eri nato.

Ma non solo... Le passeggiate a piazzale Giovanacci... il te nero con i biscotti alle quattro... le domeniche in officina Jarach & Cecconi... quando mi hai insegnato a smontare e rimontare il carburatore... il tuo orgoglio di Carabiniere e come mi misuravi perché mi avresti voluto Corazziere... l'accompagnarti alla caccia e infilarmi in un pantano da cui mi hai dovuto estrarre... Le corse con il carro armato nel piazzale del battaglione... la tua FIAT 127 con cui mi hai insegnato a guidare... Il paese dove eri nato 96 anni fa, il ciucci...

E i tuoi interminabili racconti delle tue avvertire di guerra... Tutto questo ed altro mi hai regalato nella tua vita. Ma soprattutto il ricordo di un lavoratore indefesso e di una persona integerrima come ce ne sono poche. Se esiste il paradiso tu hai l'ingresso garantito di diritto, ma di certo esiste la vita eterna, perché ora che non ci sei più vivrai per sempre nei miei più bei ricordi.

Grazie nonno Carmine...


Mi sono reso conto oggi che è passato poco più di un anno da quando ho postato l’ultima volta in queste pagine. Da allora tante, tantissime cose, sono cambiate e questo giustifica un po’ il silenzio in cui mi sono rifugiato. Non è ancora il caso che scriva pubblicamente gli eventi che mi hanno riguardato in questi 365 giorni. Forse verrà il giorno in cui potrò e vorrò parlarne ampiamente e liberamente, ma quel momento, se mai verrà, è ancora molto remoto nel futuro.

Per chi mi legge, se è ancora rimasto qualcuno che lo fa, ripensandoci oggi quello che è accaduto non è niente più di quello che in fondo sono gli imprevisti della vita che spesso ti capitano quando meno te lo aspetti, cambiandola radicalmente e cambiandoti radicalmente... oppure semplicemente facendo emergere quello che sei veramente.

Quello che conta è che ci sono ancora, un po’ (molti dicono tanto) diverso, un po’ “imprevisto” io stesso. In questo periodo di grande difficoltà mista a grande rivoluzione sono riemersi un po’ di vecchi interessi e ne sono maturati molti di nuovi ed è di questo che cercherò di parlare prossimamente.

Primo fra tutti quello che oggi mi spinge a tornare a redigere questo post che spero sarà seguito da molti altri. Mi riferisco alla mia passione per lo scrivere, passione che in realtà non ho mai riconosciuto come tale se non in questo ultimo periodo della mia vita, quando essa è diventata qualcosa che mi ha gratificato molto e molto mi ha aiutato a focalizzare quelli che sono i miei pensieri e le mie idee. Mi sono trovato spesso a scrivere per varie ragioni, tra le quali anche, banalmente, il fissare concetti che diversamente sarebbero svaniti nel flusso di miei pensieri o travolti dalle emozioni. Ho scritto molto, moltissimo, per comunicare e per comunicarmi, per organizzare e riorganizzare, per verificare se, alla prova dei fatti, quello che pensavo in un dato momento si rivelava ancora vero dopo tempo.

Ci sono tante altre cose che mi hanno accompagnato, mia figlia, il ballo e la musica, la fotografia, la lettura, il cinema e il teatro, l'arte in generale, il mio lavoro. La montagna e talvolta il mare, la città e la campagna. In definitiva, come qualcuno mi ha insegnato, la "esperienza", questo valore fondamentale che vale oltre ad ogni denaro e ad ogni oggetto che possiamo comprare con esso...

Riparto da qui, dalla voglia di comunicare qualcosa... ma non chiedetemi cosa...

Bentornato Andrea.


Le modal dialog sono uno strumento molto usato nelle applicazioni per interagire con l’utente. Purtroppo, mentre in una applicazione Windows esse sono tutto sommato semplici da gestire dato che il framework ci mette a disposizione più o meno tutto ciò di cui abbiamo bisogno, così non è nelle applicazione web in cui abbiamo solo alert e confirm che sono quanto di meno user friendly si possa immaginare. Inoltre, inserire delle proprie dialog è più o meno complicato in quando richiede non solo l’inserimento del codice Javascript che le gestisce, ma anche sel markup HTML. Un doppio lavoro quindi che complica non poco la questione. Personalmente ho trovato molto proficuo usare un servizio di AngularJS, scritto in Typescript, per cercare di risolvere questo problema alla radice. Per farlo mi sono appoggiato alle Modal popop di bootstrap che sono semplici ed efficaci e gestiscono molto efficacemente la responsività. Vediamo il servizio come è realizzato:

   1: module sys.services
   2: {
   3:     export class Constants
   4:     {
   5:         static containerId: string = '#modalContainer';
   6:         static defaultModalTitle: string = 'Message';
   7:         static modalDialogId: string = '#modalDialog';
   8:     
   9:         static Negative: string = '0';
  10:         static Positive: string = '1';
  11:         static Cancel: string = '2';
  12:     
  13:         static modalYesNo: sys.services.IDialogCommand[] = [
  14:             { id: Constants.Negative, text: 'No' },
  15:             { id: Constants.Positive, text: 'Yes', style: 'btn-primary' }];
  16:         static modalYesNoCancel: sys.services.IDialogCommand[] = [
  17:             { id: Constants.Cancel, text: 'Cancel' },
  18:             { id: Constants.Negative, text: 'No' },
  19:             { id: Constants.Positive, text: 'Yes', style: 'btn-primary' }];
  20:         static modalOkCancel: sys.services.IDialogCommand[] = [
  21:             { id: Constants.Cancel, text: 'Cancel' },
  22:             { id: Constants.Positive, text: 'Ok', style: 'btn-primary' }];
  23:     
  24:         static containerMarkup: string =
  25:         '<span></span>';
  26:         static modalMarkup: string =
  27:         '<div id="modalDialog" class="modal fade"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h4 class="modal-title">Modal title</h4></div><div class="modal-body"><p>One fine body&hellip;</p></div><div class="modal-footer"></div></div></div></div>';
  28:         static modalButtonMarkup: string =
  29:         '<button type="button" class="btn" data-dismiss="modal">Close</button>';
  30:     }
  31:     
  32:     export interface IDialogCommand
  33:     {
  34:         id: string;
  35:         text: string;
  36:         style?: string;
  37:     }
  38:  
  39:     export class ModalManager
  40:     {
  41:         private container: JQuery;
  42:         private modalDialog: JQuery;
  43:  
  44:         constructor()
  45:         {
  46:             this.appendModals();
  47:         }
  48:  
  49:         private exists(name: string): boolean
  50:         {
  51:             if (this.container == undefined)
  52:                 this.container = $(Constants.containerId);
  53:  
  54:             return this.container.find(name).length != 0;
  55:         }
  56:  
  57:         private appendModals(): void
  58:         {
  59:             if (!this.exists(Constants.containerId))
  60:             {
  61:                 this.container = $(Constants.containerMarkup);
  62:                 this.container.appendTo($(document.body));
  63:             }
  64:  
  65:             if (!this.exists(Constants.modalDialogId))
  66:             {
  67:                 this.modalDialog = $(Constants.modalMarkup);
  68:                 this.modalDialog.appendTo(this.container);
  69:             }
  70:         }
  71:  
  72:         public showDialog(message: string, title: string = Constants.defaultModalTitle, commands?: IDialogCommand[], callback?: (id: string) => void)
  73:         {
  74:             this.modalDialog.find('.modal-body').text(message);
  75:             this.modalDialog.find('.modal-title').text(title);
  76:  
  77:             var footer = this.modalDialog.find('.modal-footer');
  78:             footer.empty();
  79:  
  80:             for (var i in commands)
  81:             {
  82:                 var cmd = commands[i];
  83:  
  84:                 var button = $(Constants.modalButtonMarkup);
  85:  
  86:                 button.text(cmd.text);
  87:                 button.addClass(cmd.style == undefined ? 'btn-default' : cmd.style);
  88:                 button.data('command-id', cmd.id);
  89:  
  90:                 button.click((ev) =>
  91:                 {
  92:                     var id = $(event.srcElement).data('command-id');
  93:  
  94:                     this.modalDialog.modal('hide');
  95:  
  96:                     if (callback != undefined)
  97:                         callback.apply(this, [id]);
  98:                 });
  99:  
 100:                 button.appendTo(footer);
 101:             }
 102:  
 103:             this.modalDialog.modal('show');
 104:         }
 105:     }
 106: }

Il servizio così impostato è completo di tutto ciò che serve al funzionamento. Da solo per scontato che siano reparibili le librerie suddette (AngularJS e Bootstrap). Il metodo appendModals() in particolare si occupa di creare il markup necessario utilizzando alcune stringhe costanti. Esso verifica che il markup non sia già presente ed eventualmente lo inserisce aggiungendolo al body. Questo favorisce l’utilizzo della libreria che non richiede alcuna gestione del markup HTML. L’utilizzo è molto semplice. E’ sufficiente infatti registrare il servizio assieme al controller con la seguente riga:

   1: .service('$modalManager',
   2:     () => new sys.services.ModalManager());

Avremo così a disposizione il servizio $modalManager che possiamo iniettare in un controller. A questo punto, potremo richiamare la gdialog molto semplicemente usando uno dei metodi del servizio:

   1: this.$modalManager.showDialog(
   2:     'Are you sure you want to delete the resource',
   3:     'Confirm operation',
   4:     sys.Constants.modalYesNo,
   5:     (id: string) =>
   6:     {
   7:         if (id == sys.Constants.Positive)
   8:         {
   9:             this.clocks.push(timezone);
  10:         }
  11:  
  12:         this.selectedTimezone = undefined;
  13:         this.scope().$apply();
  14:     });

La dialog è sufficientemente intelligente da gestire numerose combinazioni di pulsanti. Le costanti presenti nella dichiarazione sono di aiuto in questo ma se ne possono creare di proprie dato che si tratta a tutti gli effetti di un array di IDialogCommand.

   1: static modalOkCancel: sys.services.IDialogCommand[] = [
   2:     { id: Constants.Cancel, text: 'Cancel' },
   3:     { id: Constants.Positive, text: 'Ok', style: 'btn-primary' }];

Senza dimenticare l’uso appropriato degli stili di bootstrap.


E' di questi giorni l'annuncio che Angular 2.0 è ora completamente scritto in Typescript. Questo è forse uno dei più sorprendenti risultati della politica di Satya Nadella che sta aprendo giorno dopo giorno alle librerie open source di terze parti. E ancora più sorprendente se pensiamo che Angular è un prodotto dei team di Google che recentemente, supportato da Microsoft ha deciso di adottare questo linguaggio. La cosa che più mi entusiasma, come riportato in questo post, è che la collaborazione sarà fonte di nuovi miglioramenti per Typescript che già dalla versione 1.5 vedrà l'introduzione delle annotations, espressamente progettate per Angular. Le annotation apriranno la strada a una sorta di Reflection che tipicamente è fonte di numerose soluzioni che risparmiano lavoro. Attendiamo con ansia...


L'asincronia sta ormai diventando una questione di tutti i giorni nelle applicazioni moderne così i linguaggi come C# si sono adeguati con costrutti come async/await. Javascript, pur essendo un linguaggio ormai antico secondo i tempi cui l'informatica ci ha abituato, gestisce da sempre molte attività in modo asincrono, utilizzando il meccanismo dei callback. Un esempio è il setInterval in cui uno degli argomenti passati è la funzione da chiamare ad intervalli regolari.

Librerie come jQuery e Angular stesso espongono numerosi casi di utilizzo di metodi asincroni. L'http service di Angular ad esempio è uno di questi casi. Esso però non utilizza normali callback ma un sistema molto simile al Task<T> di C#. Le promise. In effetti da ciascuna chiamata asincrona è ritornato un oggetto Promise che dispone dei metodi then, catch e finally. Questi servono per associare un callback a ciascuno delle condizioni che i nomi dei metodi evocano.

Ma la domanda cui vogli rispondere in questo post è la seguente: come faccio ad esporre una promise da un mio metodo asicrono se esso stesso no usa un servizio che la utilizzi? E' il caso ad esempio di un metodo che visualizzi una dialog modale. Essono mo potrà mai essere sincrono perchè oltre a risultare bloccante per il browser, non sarà comunque possibile gestire una eventuale "attesa" e ritornare dal metodo alla chiusure della dialog. Quello che ci viene in soccorso è il Q service. Esso è usato dallo stesso http service è ha come unico scopo la gestione asincrona. Vediamo un esempio:

   1: public showDialog(message: string, title: string = Constants.defaultModalTitle, commands?: IDialogCommand[]): ng.IPromise<string>
   2: {
   3:     var defer: ng.IDeferred<any> = this.$q.defer<string>();
   4:  
   5:     try
   6:     {
   7:         this.modalDialog.find('.modal-body').text(message);
   8:         this.modalDialog.find('.modal-title').text(title);
   9:  
  10:         var footer = this.modalDialog.find('.modal-footer');
  11:         footer.empty();
  12:  
  13:         for (var i in commands)
  14:         {
  15:             var cmd = commands[i];
  16:  
  17:             var button = $(Constants.modalButtonMarkup);
  18:  
  19:             button.text(cmd.text);
  20:             button.addClass(cmd.style == undefined ? 'btn-default' : cmd.style);
  21:             button.data('command-id', cmd.id);
  22:  
  23:  
  24:             button.click((ev) =>
  25:             {
  26:                 var id = $(event.srcElement).data('command-id');
  27:                 this.modalDialog.modal('hide');
  28:                 defer.resolve(id);
  29:             });
  30:  
  31:             button.appendTo(footer);
  32:         }
  33:  
  34:         this.modalDialog.modal('show');
  35:     }
  36:     catch (error)
  37:     {
  38:         defer.reject(error);
  39:     }
  40:  
  41:     return defer.promise;
  42: }

Diamo per assodato che questo metodo faccia capo ad una classe che ha ricevuto una istanza del Q service come argomento del costruttore. Come segue:

   1: constructor(private $q: ng.IQService)
   2: {
   3: }

Il metodo showDialog al proprio inizio crea una istanza di una classe di tipo IDeferred<any>, dove any è il tipo del valore ritornato dal metodo in questione. L'oggetto deferred è quello che ci serve per gestire l'asincronia. Al termine del metodo infatti viene ritornata la promise che esso contiene con "defer.promise".

A questo punto è necessario invocare i callback di successo (then) e quello di fallimento (catch). Per farlo sono utilizzati i metodi "resolve" e "reject" dell'oggetto deferred.

Così facendo è possibile usare il metodo come segue:

   1: this.showDialog(
   2:     'Are you sure you want to delete the item',
   3:     'Confirm operation',
   4:     sys.Constants.modalYesNo).then(
   5:         (id: string) =>
   6:         {
   7:             if (id == sys.Constants.Positive)
   8:             {
   9:                 // delete the item here
  10:             }
  11:         });

Il sistema è l'unico consigliato. Infatti l'utilizzo dei callback normali crea problemi al sistema di databinding di AngularJS. Invece il q service è perfettamente in grado di supportarlo.


Spesso può risultare molto comodo caricare una porzione di html dal server, magari generata da una partial view di ASP.NET MVC (o magari proprio da una View, perchè no?). con angular questo è del tutto possibile grazie alla direttiva ng-include che consente di specificare l'url da cui  caricare una risorsa all'interno della pagina. Vediamo un esempio con typescript:

Per prima cosa si crea una partialview  che dimostri un po' di dinamismo. Ecco un semplice esempio:

   1: <h2>@DateTime.Now.ToLongDateString()</h2>
   2: <h3>@DateTime.Now.ToLongTimeString()</h3>

In seguito aggiungiamo al controller il codice per poterla chiamare dal browser:

   1: public ActionResult _PartialContent()
   2: {
   3:     return PartialView();
   4: }

A questo punto diciamo che l'url per raggiungere la partial view sia il seguente:

/Include/_PartialContent

Creaiamo quindi un controller come segue:

   1: class IncludeController
   2: {
   3:     count: number = 0;
   4:     includeUri: string = undefined;
   5:  
   6:     click(): void
   7:     {
   8:         this.includeUri = '../Include/_PartialContent?ts=' + (++this.count).toString();
   9:     }
  10: }
  11:  
  12: angular.module('include', ['ngRoute'])
  13:     .controller('includeIndex', IncludeController);

Nel controller usiamo una variabile "count" per tenere conto delle volte in cui l'utente clicca il pulsante di test. Questo valore viene accodato all'uri della partial-view per forzarne il caricamento a ciascun click. L'uri così calcolato viene riposto nella proprietà includeUri. Vediamo ora la view:

   1: @{
   2:     ViewBag.Title = "Test Include";
   3: }
   4: <div>
   5:     &nbsp;
   6: </div>
   7: <div ng-app="include" ng-controller="includeIndex as ct" class="row">
   8:     <form>
   9:         <button type="button" class="btn btn-primary" ng-click="ct.click();">Click Me!</button>
  10:         <p ng-show="ct.count>0">clicked {{ct.count}} times</p>
  11:         <div ng-include="ct.includeUri"></div>
  12:     </form>
  13: </div>
  14: @section Scripts {
  15:     <script src="~/Scripts/Views/Include/index.js"></script>
  16: }

Niente più di un normale binding, con un pulsante per invocare la funzione click(), la visualizzazione del count e l'assegnazione della direttiva ng-include sulla variabile includeUri. Il risultato è che la partial view viene inclusa all'interno delle pagina ogni volta che clicchiamo il pulsante.

Interessante notare che mediante questa tecnica possiamo agevolmente caricare nella pagina qualunque tipo di file il server sia in grado di servire. Se ad esempio all'url della partial sostituiamo quello del file TS vedremo apparire il codice.


Sempre più spesso, nelle moderne applicazioni web, il codice Javascript di una pagina ha la necessità di accedere ad una webapi. Questo è certamente il più semplice metodo per attivare la pagina caricando informazioni dal server senza necessariamente effettuare il refresh dell'intera pagina. La chiamata può essere necessaria per riempire una semplice dropdowlist il cui contenuto dipende da qualche altro valore impostato in una form, piuttosto che una lista di risultati di una ricerca. Qualunque sia il contenuto, l'operazione è sempre quella di richiemare un metodo di una webapi e in seguito alla risposta deserializzare il json per popolare l'interfaccia utente.

In casi come questi ho trovato molto utile usare una classe proxy, mimando quello che avviene in C# quando si interroga un servizio WCF. La cosa interessante è che le WebApi mettono a disposizione di un ApiExplorer che è in grado di fare l'inspect della api stessa e restituire tutti i dettagli quali i metodi, i loro parametri, tipi di ritorno etc.. Grazie ad esso è possibile scrivere il seguente metodo:

   1: public abstract class ApScriptableController : ApiController
   2: {
   3:     /// <summary>
   4:     /// Il metodo restituisce lo script Javascript che consente di interrogare il controller
   5:     /// </summary>
   6:     /// <returns>Ritorna il </returns>
   7:     [HttpGet]
   8:     public HttpResponseMessage GetScript()
   9:     {
  10:         ApiExplorer explorer = new ApiExplorer(this.Configuration);
  11:  
  12:         StringBuilder builder = new StringBuilder();
  13:  
  14:         builder.Append("var __extends = this.__extends || function (d, b) {");
  15:         builder.Append("    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];");
  16:         builder.Append("    function __() { this.constructor = d; }");
  17:         builder.Append("    __.prototype = b.prototype;");
  18:         builder.Append("    d.prototype = new __();");
  19:         builder.Append("};");
  20:  
  21:         var actions = (from api in explorer.ApiDescriptions
  22:                        where  api.ActionDescriptor.ControllerDescriptor.ControllerType.IsAssignableFrom(this.GetType())
  23:                        orderby api.ActionDescriptor.ActionName ascending
  24:                        select api).ToArray();
  25:  
  26:         if (actions.Count() > 0)
  27:         {
  28:             string controllerName = actions.First().ActionDescriptor.ControllerDescriptor.ControllerName;
  29:             controllerName = controllerName.Substring(0, 1).ToUpper() + controllerName.Remove(0, 1);
  30:  
  31:             builder.AppendFormat("var {0}Proxy = (function (_super) {{", controllerName);
  32:             builder.AppendFormat("    __extends({0}Proxy, _super);", controllerName);
  33:             builder.AppendFormat("    function {0}Proxy(baseUri, accessToken, context) {{", controllerName);
  34:             builder.Append("        _super.call(this, baseUri, accessToken);");
  35:             builder.Append("        this.context = context;");
  36:             builder.Append("    }");
  37:  
  38:             foreach (var item in actions)
  39:             {
  40:                 builder.AppendFormat("    {1}Proxy.prototype.{0} = function (value) {{", item.ActionDescriptor.ActionName, controllerName);
  41:                 builder.AppendFormat("        return _super.prototype.callApi.call(this, '{0}', value, this.context);", item.RelativePath);
  42:                 builder.Append("    };");
  43:             }
  44:  
  45:             builder.AppendFormat("    return {0}Proxy;", controllerName);
  46:             builder.Append("})(sys.net.Proxy);");
  47:         }
  48:  
  49:         var response = new HttpResponseMessage(HttpStatusCode.OK);
  50:         response.Content = new StringContent(builder.ToString(), Encoding.UTF8, "text/javascript");
  51:         return response;
  52:     }
  53: }

Il codice rappresenta una classe base da utilizzare per i controller delle WebApi. Essa implementa un metodo GetScript che non fa altro che ispezionare i metodi della api stessa e genera di conseguenza un codice Javascript che rappresenterà il proxy della WebApi. In coda al metodo, le ultime righe cambiano il content-type della risposta impostandolo e text/javascript. In questo modo sarà possibile fornire l'url della api ad un tag script e di conseguenza far leggere il codice e caricarlo nel browser.

   1: <script src="~/api/Home/getscript"></script>

L'ultimo tassello di questo piccolo puzzle è una classe Typescript che rappresenta la base per il proxy Javascript. Il codice generato infatti fa uso delle funzioni e dei tipi presenti in questo breve snippet.

   1: module sys.net
   2: {
   3:     // represents a base for api responses
   4:     export interface IApiResponseBase 
   5:     {
   6:         HasErrors: boolean
   7:         Message: string;
   8:     }
   9:  
  10:     // represents a successful response from an api
  11:     export interface IApiResponse<T> extends IApiResponseBase
  12:     {
  13:         Result: T;
  14:     }
  15:  
  16:     export class Proxy 
  17:     {
  18:         // creates and initializes the proxy with the given base uri
  19:         constructor(private baseUri: string, private accessToken: string)
  20:         { }
  21:  
  22:         // calls a generic API with the specified route and argument
  23:         public callApi<T>(route: string, argument: any, context?: string): JQueryPromise<T>
  24:         {
  25:             var uri = this.baseUri + route;
  26:  
  27:             return $.Deferred(
  28:                 (deferred: JQueryDeferred<T>) =>
  29:                 {
  30:                     $.ajax({
  31:                         url: uri,
  32:                         type: 'POST',
  33:                         data: JSON.stringify(argument),
  34:                         contentType: 'application/json; charset=utf-8',
  35:                         beforeSend: (xhr) =>
  36:                         {
  37:                             xhr.setRequestHeader('Authorization', 'Bearer ' + this.accessToken);
  38:  
  39:                             if (context != undefined)
  40:                                 xhr.setRequestHeader('X-Tsf-Context', context);
  41:                         }
  42:                     })
  43:                         .done(
  44:                         (retVal: IApiResponse<T>) =>
  45:                         {
  46:                             if (retVal.HasErrors)
  47:                                 deferred.reject(retVal);
  48:                             else
  49:                                 deferred.resolve(retVal.Result);
  50:                         })
  51:                         .fail((err: any) => deferred.reject(this.mapToError(uri, err)));
  52:                 }).promise();
  53:         }
  54:  
  55:         // maps any error information to a common object
  56:         private mapToError(uri: string, err: any): IApiResponseBase
  57:         {
  58:             return <IApiResponseBase>
  59:                 {
  60:                     Message: 'Api "' + uri + '" reported an error: ' + err.statusText,
  61:                     HasErrors: true
  62:                 };
  63:         }
  64:     }
  65: }

Una volta che il codice sia caricato nell'ordine corretto, avremo a disposizione una classe che riporta il nome del controller seguito dalla parola Proxy. Perciò se il controller ha il nome "Home" il proxy sarà "HomeProxy".

   1: var proxy = new HomeProxy(sys.Application.ServiceUri, sys.Application.AccessToken, sys.Application.Context);
   2: proxy.GetValuesForList()
   3:     .done((result) =>
   4:      {
   5:         // TODO: process here
   6:      });

Il proxy fa uso delle promise di jQuery perciò il suo utilizzo è molto semplice e gestisce perfettamente la asincronicità.


Capita talvolta (spesso in effetti), che quando entrate in una pagina in cui sia utilizzato AngularJS per una frazione di secondo appaiano le notazioni del binding che spariscono poco dopo quando il databinding viene applicato. Questo accade perchè in quella frazione di secondo in cui il browser scarica il codice e avvia angular, tutte quelle parentesi graffe sono niente più che semplice testo e in gran parte esse sono visualizzate dal browser perchè occupano posizioni "visibili".

Per evitare questo comportamento viene in aiuto la direttiva ng-Cloak. Essa, come testimonia la documentazione ha proprio lo scopo di applicare un "display:none" agli elementi, e questo funzione nella maggioranza dei casi. Tuttavia anche se applichiamo la direttiva ng-Cloak (ad esempio al body per generalizzare, ma anche ad un singolo elemento come invece è consigliabile) talvolta le graffe appaiono comunque. Questo è imputqabile al medesimo ritardo. Per evitarlo è opportuno aggiungere al proprio css il seguente:

   1: [ng\:cloak], [ng-cloak], .ng-cloak {
   2:   display: none !important;
   3: }

In questo modo il CSS cercherà tutti gli elementi con l'attributo ng-Cloak e li nasconderà automaticamente.

Il trick è spiegato più estensivamente qui: http://stackoverflow.com/questions/11249768/angularjs-ng-cloak-ng-show-elements-blink


Ho sempre avuto l’insana convinzione che fosse meglio vivere, sempre e invariabilmente, scommettendo il possibile contro il probabile. Questo perchè in definitiva il probabile esiste e basta… è probabile, e quindi serve il minimo sforzo perchè di verifichi, ma da esso non ti puoi aspettare sorprese, niente di positivo, niente che faccia evolvere la tua situazione in meglio, niente che sia in più rispetto a quello che tutti si aspettano. Il probabile è il minimo sindacale, è l’oppressore che vince sull’oppresso, è lo stesso quotidiano tutti i giorni, è il latte consegnato all’uscio, quello che non ti fa “mandare dalla mamma”.

Il possibile invece è creativo. Lui non esiste e te lo devi costruire, pezzo per pezzo, con fantasia e immaginazione. Il possibile in realtà sono i tuoi sogni, quelli che fai mentre guidi sulla via del ritorno dall’ufficio, e che tutti il più delle volte archiviano dicendo… “ah, impossibile!”.

Alla fine il probabile è una vacanza in una comune località di mare dove il massimo che ti puoi aspettare è che un ombrellone sia un po’ fuori posto. Arriva il bagnino, lo sistema e tutto torna nell’ambito della semplice probabilità. Il possibile invece è una settimana in barca, alla scoperta di angoli del mondo che nemmeno ti aspettavi potessero esistere, pieno del colore, del profumo e delle sensazioni che mai avresti immaginato.

Il problema è che mentre il probabile non ti delude mai, dato che non ti da nulla, il possibile è armato di scimitarra ed è pronto, in ogni istante, a menarti un fendente che ti lascia tramortito. Succede, spesso, che inseguendo il possibile si rimanga trafitti, bastonati, delusi e tramortiti, ma alla fine ne vale sempre la pena. Vale la pena il sapere di aver fatto qualcosa che ti ha cambiato o che ha cambiato, sentire la soddifazione di essere riusciti a lasciare un segno, a migliorare le cose, a… a… a… … anche se il prezzo il da pagare il più delle volte è lo stare male perchè il probabile ha vinto ancora una volta.

Già, impossibile… tutti invariabilmente lo hanno detto almeno una volta, i più se lo dicono sempre con insistenza. Il risultato è l’aver dovuto archiviare con una sola parola un sogno, e aver chiuso un libro di speranze senza nemmeno provare a renderlo concreto. Anche io spesso, ma mai volentieri, cedo al probabilismo, alla tentazione della uniformità e prevedibilità. Ma spesso, soprattutto se mi fermo a pensarci, allora il possibile mi illumina e braccio a braccio al mio ottimismo mi guida alla scoperta di aspetti e possibilità che nemmeno osavo esprimere.

Lasciamo la noia a quei dannati probabilisti. La vita sta nel possibile.