AngularJS e Laravel Finishing Building a CRM

Quando creiamo un'applicazione a singola pagina dovremmo usare un qualche tipo di framework per fare un po 'di lavoro per noi in modo che possiamo concentrarci sulla funzionalità reale. 

AngularJS si adatta perfettamente alla perfezione, perché funzionalità come l'iniezione di dipendenza dinamica e l'associazione bidirezionale dei dati sono semplicemente grandi. A volte richiediamo anche un qualche tipo di server. Se hai scelto PHP, Laravel potrebbe essere la tua migliore opzione, poiché è facile da usare e piuttosto potente.

In questa parte del tutorial, costruiremo il front-end della nostra applicazione usando AngularJS. Angolare è una struttura davvero unica. Invece di astrarre l'HTML o fornire un modo di manipolare il DOM, hanno esteso l'HTML per far fronte al fatto che non era sicuramente progettato per funzionare con dati dinamici. 

A causa di ciò Angular potrebbe aver bisogno di un po 'più di apprendimento rispetto ad altri framework, ma vale davvero il tempo speso.


Preparazione

Prima di iniziare a programmare il nostro front-end, dobbiamo modificare un po 'la parte di Laravel. Vai a app / views, elimina il materiale di esempio presente e crea il file denominato home.php. Ora creiamo il layout. 

Inizia con il DOCTYPE e il html etichetta:

 

Come puoi vedere stiamo già utilizzando alcune cose di AngularJS: il ng-app direttiva. Questo dice ad Angular di usare il modulo chiamato App per questa applicazione (lo definiremo in seguito). Successivamente, aggiungi il capo con un titolo e CSS:

Gestione del cliente 

Ora puoi mettere il copione tag con Angular, il modulo di routing e la nostra app:

  

 Questa direttiva dice ad Angular di inserire il modello richiesto in quell'elemento.

Dopodiché abbiamo solo bisogno di aggiungere un percorso per mostrare il modello (in app / routes.php). Aggiungi questo prima delle rotte per i controller:

Route :: get ('/', function () return View :: make ('layout'););

Ora se si avvia il server (con servire php artigianale) dovresti vedere il nostro layout di base quando navighi su http: // localhost: 8000 / nel tuo browser:

Lo stile

Questo articolo non si concentrerà su nulla relativo ai CSS, ma per rendere l'app più piacevole alla vista mentre stai sviluppando aggiungeremo un po 'di stile. Vai al pubblico/ directory della tua app (è accanto a app /) e creare il style.css con questo codice in esso:

body font-family: Calibri, sans-serif; larghezza: 800px; margine: auto;  a cursor: pointer; colore blu; decorazione del testo: nessuna;  table width: 100%;  table thead tr background: #ccc;  table tbody tr background: #ddd;  table tbody tr: nth-child (2n + 1) background: #eee;  table tr td: nth-child (1) text-align: center;  table tr td: nth-child (3), table trtd: nth-child (4) text-align: right;  .error color: red; 

Ora apri l'app nel tuo browser e il layout dovrebbe essere centrato con un font più bello nell'intestazione:

Struttura dell'applicazione di base

Inizieremo con una dichiarazione del modulo. I moduli in Angular sono praticamente la stessa cosa che in qualsiasi libreria AMD, ma con l'aggiunta dell'iniezione delle dipendenze che è una cosa davvero utile, come vedrai. Ecco la dichiarazione del nostro App modulo:

var app = angular.module ('app', ['ngRoute']);

La sintassi è semplice: prima va il nome del modulo e quindi l'array di dipendenze, che useremo solo ngRoute qui per gestire la navigazione, che andrà dopo.

Routing

Il routing è definito nel modulo config () metodo:

app.config (funzione configure ($ routeProvider) 

Qui è quando l'iniezione di dipendenza entra per la prima volta - il nostro richiamo richiederà $ routeProvider come l'unico argomento, e questo modulo verrà iniettato da Angular.

Devi assicurarti che i nomi degli argomenti siano esattamente uguali ai nomi dei moduli, perché Angular li usa per abbinare i moduli appropriati.

Ora usiamo il $ routeProvider per impostare i percorsi:

$ routeProvider .when ('/', controller: 'CustomersController', templateUrl: './templates/customers.html') .when ('/ cliente /: id', controller: 'CustomerController', templateUrl: ' ./templates/customer.html ') .otherwise (redirect:' / '); );

Come puoi vedere per definire un percorso devi chiamare il quando() metodo del fornitore (si noti che possono essere concatenati). 

Il primo parametro è l'URI e il secondo è un oggetto con le opzioni del percorso. Qui, alleghiamo controller e modelli appropriati per ogni percorso. Nella seconda usiamo anche : id alla fine per contrassegnare un parametro di percorso che useremo in seguito. Il altrimenti() metodo definisce cosa succederà se si accede a qualsiasi altro URI.


Fabbrica

Prima di scrivere i controller, dobbiamo creare una cosa chiamata fabbrica. fabbrica è una funzione che restituisce un servizio, che è utile se si desidera separare qualsiasi funzione di acquisizione / impostazione dei dati dai controller (che è ovviamente ciò che si desidera sempre fare). Lo definiamo usando il fabbrica() metodo del modulo:

app.factory ('Data', funzione Data ($ http) 

Il primo parametro è il nome del servizio e il secondo è una funzione che restituisce il servizio che verrà creato utilizzando questo factory.

Useremo il $ http modulo per accedere al nostro server usando Ajax. Fornisce metodi di scorciatoia per tutti i metodi HTTP e ognuno di loro restituisce una promessa (se non si sa che cosa è dare un'occhiata qui e qui).

Dobbiamo restituire il servizio come oggetto con tutti i metodi che verranno utilizzati nei nostri controllori:

ritorno 

Il primo sarà OTTENERE tutti i clienti in modo che possiamo mostrarli in un elenco:

getCustomers: function getCustomers () return $ http.get ('/ customers / all'); ,

Il secondo sarà OTTENERE solo un cliente dal suo id:

getCustomer: function getCustomer (id) return $ http.get ('/ customers? id =' + id); ,

Terza volontà INVIARE la richiesta di aggiungere utenti al database:

addCustomer: function addCustomer (data) return $ http.post ('/ customers', data); ,

Il secondo argomento in $ Http.post () sono i dati che verranno inviati al server.

Il prossimo sarà ELIMINA il cliente con il id fornito:

removeCustomer: function removeCustomer (id) return $ http.delete ('/ customers? id =' + id); , 

Ora ce ne saranno alcuni simili per le transazioni. Uno per averli tutti:

getTransactions: function getTransactions (id) return $ http.get ('/ transactions? id =' + id); ,

Uno per aggiungerne uno nuovo:

addTransaction: function addTransaction (data) return $ http.post ('/ transactions', data); ,

E uno da eliminare:

removeTransaction: function removeTransaction (id) return $ http.delete ('/ transactions? id =' + id); );

Controller clienti

I controller in Angular sono (come suggerisce il nome) un modo per controllare il comportamento dell'applicazione. Ne avremo uno per ogni modello. Per prima cosa ne faremo uno per la pagina principale. Inizia definendolo:

app.controller ('CustomersController', funzione CustomersController ($ scope, dati) 

Il secondo parametro qui è la funzione di costruzione per il controller. È il primo argomento ($ portata) è il collegamento tra DOM e controller. È il cuore del binding bidirezionale dei dati di Angular. Il secondo è il servizio dalla fabbrica che abbiamo creato in precedenza.

Ottenere la lista

Ora otterremo la lista dei clienti dal server usando il nostro servizio:

. Data.getCustomers () di successo (parseCustomers);

Tutte le promesse in Angular forniscono il successo() e errore() metodi che possono essere utilizzati per aggiungere callback appropriati. Ora definiamo la funzione che analizzerà i dati in arrivo per mostrarli sulla pagina:

 function parseCustomers (data) $ scope.customers = data; 

Sì, è tutto ciò che serve per alimentare il modello con i dati. Non ce n'è bisogno innerHTML/appendChild ()-codice ish.

Aggiunta di nuovi clienti

Dobbiamo inoltre fornire la possibilità di aggiungere e rimuovere clienti. Per prima cosa creiamo un oggetto nell'ambito in cui terremo i dati del nuovo cliente:

$ scope.newCustomer = name: ", email:";

In questo modo possiamo evitare di accedere a DOM quando l'utente aggiunge un cliente. Ora la funzione che aggiungerà effettivamente il cliente: 

$ scope.addCustomer = function addCustomer () 

Poiché il nome completo dell'utente verrà visualizzato nella tabella, l'input per esso sarà lo stesso, quindi dobbiamo dividerlo per ottenere il nome e il cognome:

var names = $ scope.newCustomer.name.split (");

Ora chiamiamo la funzione appropriata dalla nostra fabbrica con i dati di $ portata:

Data.addCustomer (first_name: nomi [0], last_name: nomi [1], email: $ scope.newCustomer.email)

Dopo di ciò, aggiungiamo gli ascoltatori di successo e di errore alla promessa restituita:

.successo (customerAddSuccess) .error (customerAddError); 

Definiamo prima la callback di successo:

function customerAddSuccess (data)  

Il dati argomento contiene il testo della risposta. Dobbiamo cancellare il $ scope.error variabile:

$ scope.error = null;

Spingere il cliente appena aggiunto a $ scope.customers:

$ Scope.customers.push (dati);

E impostare $ scope.newCustomer al suo stato iniziale per cancellare gli input:

$ scope.newCustomer = name: ", email:"; 

Il callback dell'errore imposterà semplicemente il $ scope.error variabile al testo ricevuto dal server:

function customerAddError (data) $ scope.error = data;  

Rimozione dei clienti

La funzione di rimuovere il cliente prenderà il suo id come parametro:

$ scope.removeCustomer = function removeCustomer (id) 

Mostreremo anche una finestra di conferma in modo che l'utente abbia la possibilità di annullare l'azione:

if (conferma ('Vuoi veramente rimuovere questo cliente?')) 

Se l'utente è sicuro di voler continuare, eliminiamo il cliente:

Data.removeCustomer (id) .success (customerRemoveSuccess); 

Il callback qui dovrà rimuovere il cliente da $ scope.customers usando l'id ottenuto dal server:

function customerRemoveSuccess (data) var i = $ scope.customers.length; while (i--) if ($ scope.customers [i] .id == data) $ scope.customers.splice (i, 1); 

Il risultato

Il codice completo dovrebbe assomigliare a questo:

app.controller ('CustomersController', funzione CustomersController ($ scope, Data) Data.getCustomers (). success (parseCustomers); function parseCustomers (dati) $ scope.customers = data; $ scope.newCustomer = nome: ", email:"; $ scope.addCustomer = function addCustomer () var names = $ scope.newCustomer.name.split ("); Data.addCustomer (first_name: nomi [0], last_name: nomi [1] , email: $ scope.newCustomer.email) .success (customerAddSuccess) .error (customerAddError); function customerAddSuccess (data) $ scope.error = null; $ scope.customers.push (dati); $ scope.newCustomer = nome: ", email:"; funzione customerAddError (data) $ scope.error = data; $ scope.removeCustomer = function removeCustomer (id) if (conferma ('Vuoi veramente rimuovere questo cliente? ? ')) Data.removeCustomer (id) .success (customerRemoveSuccess); function customerRemoveSuccess (data) var i = $ scope.customers.length; while (i--) if ($ scope.customers [i ] .id == data) $ scope.customers.splice (i, 1););

Modello di clienti

Ora per mostrare effettivamente i dati ai nostri utenti dobbiamo creare un modello. L'abbiamo definito nel percorso da fare ./templates/customers.html, quindi crea il pubblici / templates directory e il customers.html file in esso.

Per prima cosa aggiungi l'intestazione in modo che l'utente sappia dove si trova:

Clienti

Successivamente abbiamo bisogno di una tabella con una buona intestazione per mostrare i dati:

Ora aggiungi il tbody elemento. Ed è qui che entra di nuovo in gioco la magia di Angular. Usando il ng-repeat direttiva diciamo ad Angular di ripetere l'elemento:

La sintassi è come in JavaScript per ... in ciclo continuo. Ora possiamo accedere a cliente variabile per ottenere tutti i dati di cui abbiamo bisogno. In Angolare si inseriscono variabili usando doppie parentesi graffe:

   identificativo del cliente   [-] customer.first_name customer.last_name   customer.email  

C'è anche un ng-click direttiva che fungerà da al clic callback dell'evento, lo usiamo per aggiungere la possibilità di rimuovere i clienti. Avanti c'è un footer con input in modo che l'utente possa aggiungere nuovi clienti:

    [+]  

Noi usiamo il ng-model direttiva per legare le variabili appropriate dall'ambito agli input, in modo che vengano aggiornati ogni volta che si verifica un cambiamento nel valore degli input.

L'ultima cosa da fare è mostrare un messaggio di errore se ce n'è. Per raggiungere ciò useremo ng-spettacolo direttiva che mostrerà l'elemento solo se l'espressione specificata è vera:

errore

Questo è tutto! Ora puoi aprire l'app nel tuo browser e dovresti vedere questo:

Puoi aggiungere un nuovo cliente facendo clic sul segno più nell'angolo in basso a destra della tabella.


Controller del cliente

Ora creiamo un controller per una vista a singolo cliente:

app.controller ('CustomerController', funzione CustomerController ($ scope, $ routeParams, Data) 

Ottenere i dati

Usiamo i dati del cliente $ routeParams modulo che contiene tutti i parametri del percorso come il : id abbiamo specificato in precedenza:

Data.getCustomer ($ routeParams.id) .success (parseCustomer); function parseCustomer (data) $ scope.customer = data; 

Il callback è praticamente lo stesso di CustomersController. Ora prendiamo tutte le transazioni del cliente:

Data.getTransactions ($ routeParams.id) .success (parseCustomersTransactions); function parseCustomersTransactions (data) $ scope.transactions = data; $ scope.sum = 0; for (var k in data) $ scope.sum + = parseFloat (data [k] .amount); 

Il callback è leggermente diverso dall'ultimo perché vogliamo anche mostrare la somma degli importi delle transazioni. Dobbiamo usare parseFloat () perché Laravel invia i float come stringhe.

Aggiunta di nuove transazioni

Il codice sarà molto simile a quello utilizzato per creare nuovi clienti:

$ scope.newTransaction = name: ", amount: 0; $ scope.addTransaction = function addTransaction () $ scope.newTransaction.customer_id = $ scope.customer.id; Data.addTransaction ($ scope.newTransaction) .success. (transactionAddSuccess) .error (transactionAddError); function transactionAddSuccess (data) $ scope.error = null; data.amount = parseFloat (data.amount); $ scope.transactions.push (data); $ scope.sum + = data.amount; $ scope.newTransaction = name: ", amount: 0;  function transactionAddError (data) $ scope.error = data; 

L'unica differenza è che aggiungiamo l'ID del cliente ai dati in modo che il server sappia quale sia la transazione. Anche la callback di successo è leggermente modificata, perché dobbiamo analizzare il float prima di aggiungerlo al $ portata e dobbiamo aggiungere l'importo alla nostra somma.

Rimozione delle transazioni

Il codice per removeTransaction () la funzione è quasi identica a removeCustomer essere diversi solo nei nomi delle variabili:

$ scope.removeTransaction = function removeTransaction (id) if (conferma ('Vuoi veramente rimuovere questa transazione?')) Data.removeTransaction (id) .success (transactionRemoveSuccess);  function transactionRemoveSuccess (data) var i = $ scope.transactions.length; while (i--) if ($ scope.transactions [i] .id == data) $ scope.sum - = $ scope.transactions [i] .amount; $ scope.transactions.splice (i, 1); 

Il risultato

Il controller intero dovrebbe assomigliare a questo:

app.controller ('CustomerController', funzione CustomerController ($ scope, $ routeParams, Data) Data.getCustomer ($ routeParams.id) .success (parseCustomer); function parseCustomer (dati) $ scope.customer = dati; Dati .getTransactions ($ routeParams.id) .success (parseCustomersTransactions); function parseCustomersTransactions (data) $ scope.transactions = data; $ scope.sum = 0; for (var k in data) $ scope.sum + = parseFloat ( data [k] .amount); $ scope.newTransaction = name: ", amount: 0; $ scope.addTransaction = function addTransaction () $ scope.newTransaction.customer_id = $ scope.customer.id; Data .addTransaction ($ scope.newTransaction) .success (transactionAddSuccess) .error (transactionAddError); function transactionAddSuccess (data) $ scope.error = null; data.amount = parseFloat (data.amount); $ scope.transactions.push (dati); $ scope.sum + = data.amount; $ scope.newTransaction = name: ", amount: 0; function transactionAddError (data) $ scope.error = data; $ scope.removeTransaction = functi su removeTransaction (id) if (conferma ('Vuoi davvero rimuovere questa transazione?')) Data.removeTransaction (id) .success (transactionRemoveSuccess);  function transactionRemoveSuccess (data) var i = $ scope.transactions.length; while (i--) if ($ scope.transactions [i] .id == data) $ scope.sum - = $ scope.transactions [i] .amount; $ scope.transactions.splice (i, 1); );

Modello del cliente

Il modello per singolo cliente non ha nuove direttive di Angular, quindi basta creare un file chiamato customer.html nel pubblico / templates / e inserisci questo codice qui:

Informazioni per i clienti

Nome: customer.first_name customer.last_name

E-mail: customer.email

Elenco delle transazioni

ID Nome Quantità Data
transaction.id [-] transaction.name $ transaction.amount.toFixed (2) transaction.created_at
[+]
Somma:$ sum.toFixed (2)

errore

Nota che stiamo usando toFixed (2) per arrotondare i float in modo che abbiano solo due campi decimali, perché il modo in cui Laravel gestisce i float in JSON.

Ora puoi aprire il browser e fare clic su uno dei clienti che hai creato. Dovresti vedere il controller e il modello in azione:


Conclusione

Ora se hai aggiunto alcune funzionalità dopo la prima parte, includendola nel front-end dovrebbe essere una questione di aggiungere poche righe di codice qua e là.

Spero che dopo aver finito di leggere l'articolo e che la tua app sia finita e funzionante, inizierai a pensare a come creare applicazioni a pagina singola senza AngularJS e qualsiasi app PHP senza Laravel. Fatemi sapere se avete avuto problemi con i quadri presentati qui.