Skip to content →

Perchè la mia app Angular non funziona? 7 Errori comuni

Risolvere i problemi sulla tua applicazione Angular può essere davvero una sfida. Diventa tutto molto più difficile quando la nostra app non funziona e tutto ciò che ci restituisce sono alcune linee rosse “critiche” nella console.

Soprattutto quando sei alla prime armi, questi problemi possono trasformare il processo di sviluppo in un vero dramma.

Ma fidati, alla fine non sarà così doloroso. Tutto quello che devi fare è evitare alcuni errori molto comuni, che quasi tutti gli sviluppatori Angular devono affrontare e sbatterci almeno una volta.

Leggendo questo articolo che andrà ad analizzare i 7 errori più comuni, il tuo sviluppo potrebbe avere meno intoppi :).

Vi spiegherò per ogni punto perchè è una bad practice o semplicemente un errore, e vi indirizzerò nella giusta direzione con almeno una possibile soluzione.

1) Importare i moduli Angular richiesti

L’errore più comune quando si è alla prime armi è quello di non importare i moduli richiesti. Perchè? Semplicemente perchè non si conosce abbastanza il framework. Avere una overview completa di Angular richiede un pò di tempo.

L’errore potrebbe presentarsi così:

Can't bind to 'ngModel' since it isn't a known property of 'input'

Questo errore ci indica che il modulo angular Forms non è stato importato nel nostro modulo.

Mentre se otteniamo il seguente errore:

Unhandled Promise rejection: No provider for HttpClient!

Significa che il modulo HttpClient non è stato importato nel nostro modulo root.

Soluzione

La soluzione è semplice: dobbiamo importare i moduli mancanti nel nostro modulo. Nella maggior parte dei casi, tali moduli dovranno essere importati nell’AppModule della tua app.

Importiamo i moduli HttpClientModule e FormModule

Ovviamente per evitare che la dimensione della nostra applicazione cresca significativamente, dobbiamo importare SOLO i moduli necessari.

Questa best practice non è soltanto applicabile ai moduli del framework, ma per ogni modulo custom che tu vorrai usare.

Prendiamo come esempio la libreria Angular Material: per utilizzare il modulo Sidenav esiste un modulo apposito MatSidenavModule e così via.

Quindi in base alle necessità del nostro modulo possiamo o meno importare determinati moduli:

...
MatSidenavModule
MatCheckboxModule
...

2) Non usare riferimenti al DOM per elementi che ancora non esistono (@ViewChild)

Con l’aiuto del decoratore @ViewChild, Angular rende molto facile far riferimento a specifici elementi figlio (nodi o componenti html) del componente.

Bisogna semplicemente aggiungere # seguito dal nome. Ad esempio:

<div #myFirstDiv></div>

Possiamo ora fare riferimento a quell’elemento dal nostro componente. Se si tratta di un componente, possiamo chiamare i suoi metodi pubblici e accedere alle sue proprietà. Se si tratta di un semplice elemento HTML, possiamo cambiare il suo stile, i suoi attributi o i suoi figli.

Angular assegna automaticamente il riferimento ad una proprietà del nostro componente se decoriamo tale proprietà con il decoratore @ViewChild(). Assicuriamoci di passare il nome di riferimento al decoratore. Ad esempio @ViewChild(‘myFirstDiv’).

Problema

La direttiva @ViewChild() è molto utile. Ma dobbiamo essere attenti che l’elemento referenziato esista realmente.

La domanda nasce spontanea: perchè non dovrebbe esistere?

Ci sono diversi motivi per cui un elemento a cui si fa riferimento non potrebbe effettivamente esistere.

Il motivo più comune è che il browser non ha ancora completato il caricamento e quindi tale elemento non è stato aggiunto nel DOM.

Ovviamente se provi ad accedere a questo elemento in questa fase, esso risulterà undefined o null.

Un esempio di accesso al DOM quando non esiste è nel costruttore del componente nella callback del ciclo di vita ngOnInit.

Vediamo un esempio:

Soluzione

Ricordate l’evento DOMContentLoader o la super classica callback di Jquery $(document).ready()? Ecco il meccanismo usato da Angular è il medesimo: ngAfterViewInit . La callback in questione fa parte del lifecycle hook di Angular.

ngAfterViewInit è una callback che viene invocata quando tutte le viste dei componenti e dei figli vengono inizializzate.

Ritornando all’esempio precendente, potremmo variare il codice in questo modo:

Ottimo! Abbiamo risolto il nostro problema. Ma attenzione ci sono ancora altre insidie da tener in considerazione.

Come abbiamo detto precedentemente, possiamo accedere ad un elemento nel DOM quando quest’ultimo è effettivamente aggiunto.

Se avessimo una casistica del genere:

Gli elementi con una direttiva * ngIf (a false nel nostro caso), verrebbero completamente rimossi dal DOM.

Quindi non possiamo accedervi in ​​quel caso.

Per prevenire crash della nostra applicazione, dobbiamo effettivamente fare un check al nostro riferimento se è null o meno.

In pratica il nostro codice diventa:

3) Non manipolare il DOM direttamente

Manipolare direttamente il DOM in Angular non è considerata una bad practice. Probabilmente la nostra app funzionerà correttamente su browser ma in ambienti diversi come Angular Universal questo potrebbe non accadere. In sintesi Angular Universal consente di renderizzare la nostra app Angular lato server.

Facciamo un esempio:

Soluzione

Angular mette a disposizione un’API ad hoc per la manipolazione del DOM: Render2

Con l’aiuto di questa API, possiamo fare tutto ciò a cui siamo abituati quando lavoriamo con il DOM.

Ecco un esempio chiarificatore:

Come detto possiamo fare davvero qualsiasi cosa, e quindi, ti consiglio ti dare uno sguardo alla documentazione ufficiale.

4) Angular Guards non sono una feature di sicurezza

Angular Guard è un ottimo modo per limitare artificialmente l’accesso a determinate rotte.

Il classico esempio potrebbe essere quello di inibire l’accesso a determinate pagine senza avere effettuato il login.

Definiamo il nostro “Guard”
Guard in azione 🙂

Problema

Questa resta una soluzione più che valida per “inibire” l’accesso a determinate rotte ma, come qualsiasi altra soluzione “web”, non è sicura al 100%.

Poiché forniamo il codice sorgente completo a potenziali utenti “pericolosi”, l’applicazione può essere modificata in qualsiasi modo. Ciò significa che la nostra guardia può essere facilmente aggirata commentando alcune righe.

Soluzione

Aggiungere una soluzione server-side diminuisce il rischio di intrusione ai nostri dati all’interno dell’app. Un esempio potrebbe essere l’utilizzo di jwt (Javacript Web Token).

5) Dichiarare i componenti solo una volta

Quando iniziamo a raggruppare la nostra applicazione in moduli, che è tendenzialmente una best practice, tra l’altro, probabilmente incontrerai un problema molto comune:

Un componente può essere dichiarato solo in un modulo!

Ma cosa possiamo fare se vogliamo utilizzare il nostro componente in più moduli?

La soluzione è semplice. Basta aggiungere il tuo componente in un modulo. Probabilmente un modulo per componente è un pò eccessivo, quindi perché non creare un modulo di componenti? Quel modulo può essere importato in altri moduli e lì potrai usare i tuoi componenti.

6) Ottimizzare e velocizzare la tua app utilizzando *ngIf invece che l’attributo [hidden]

Spesso si fa confusione tra l’utilizzo della direttiva hidden e quella *ngIf.

La principale differenza è che la direttiva ngIf , invece di nascondere solo gli elementi contrassegnati (quello che effettivamente fa la direttiva hidden), li rimuove dal DOM.

A parte i possibili miglioramenti in termini di performance, la soluzione ngif sembra molto più pulita. Quindi la consiglio come standard in questi scenari.

<div *ngIf="!isHere"></div>

7) Utilizza i Service per evitare problemi di manutenibilità

Come consiglio generale, è sempre buona pratica estrapolare la business logic all’interno di servizi. In questo modo, risulta più facile da gestire, in quanto una eventuale modifica potrà essere implementata in pochi secondi e sarà ben localizzata e non dovremmo impazzire nel modificare n-mila righe di codice..

Questo consiglio è certamente vero quando si usa HttpClient. Dovrebbe essere sempre racchiuso all’interno di un servizio centralizzato. In questo modo, risulta facilmente testabile e sarà semplice apportare modifiche. Ad esempio, il tuo back-end richiede un nuovo header da passare ad ogni richiesta dopo l’aggiornamento. Senza un servizio centralizzato, dovresti modificare molteplici linee di codice all’interno della tua app.

Spero che questo articolo sia stato utile. Se si, condividilo con i tuoi amici, colleghi o con chi ritieni possa essere interessato.

Published in Angular World

Comments

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *