AngularJS și Laravel Finalizarea construirii unui CRM

Atunci când creați o aplicație de o singură pagină, ar trebui să folosim un anumit cadru pentru a face o treabă pentru noi, astfel încât să ne putem concentra asupra funcționalității reale. 

AngularJS se potrivește perfect aici, deoarece caracteristici cum ar fi injecția dinamică a dependenței și legarea datelor bidirecționale sunt doar minunate. Uneori avem nevoie și de un server. Dacă ați ales PHP, atunci Laravel ar putea fi cea mai bună opțiune, deoarece este ușor să lucrați și destul de puternic.

În această parte a tutorialului, vom construi front-end-ul aplicației noastre folosind AngularJS. Angular este un cadru cu adevărat unic. În loc să abstracteze codul HTML sau să ofere o modalitate de manipulare DOM, ei au extins codul HTML pentru a se ocupa de faptul că acesta nu a fost desigur proiectat să funcționeze cu date dinamice. 

Din acest motiv, unghiul ar putea avea nevoie de învățare mai mult decât alte cadre, dar merită cu adevărat timpul petrecut.


preparare

Înainte de a începe programarea front-end, trebuie să modificăm puțin partea Laravel. Mergi la app / vizualizări, ștergeți chestiile de exemplu care există și creați fișierul numit home.php. Acum să creăm aspectul. 

Începeți cu DOCTYPE si html etichetă:

 

După cum puteți vedea, noi deja folosim unele lucruri AngularJS - ng-app directivă. Acest lucru îi spune lui Angular să utilizeze modulul numit aplicaţia pentru această aplicație (o vom defini mai târziu). După aceea, adăugați cap cu un titlu și CSS:

Managementul clientilor 

Acum poți pune scenariu tag-uri în modul Angular, modul de rutare și aplicația noastră:

  

 Această directivă îi spune lui Angular să pună șablonul care a fost solicitat în acest element.

După aceasta, trebuie să adăugăm doar o rută pentru a afișa șablonul (în app / routes.php). Adăugați acest lucru înainte de rutele pentru controlori:

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

Acum, dacă porniți serverul (cu php artisan servi) ar trebui să vedeți aspectul nostru de bază când navigați la http: // localhost: 8000 / în browserul dvs.:

Stilul

Acest articol nu se va concentra pe nimic legat de CSS, dar pentru a face aplicația mai plăcută pentru ochi în timp ce vă dezvoltați, vom adăuga un anumit stil. Mergeți la public/ directorul aplicației dvs. (este lângă app /) și creați style.css cu acest cod în el:

corp font-familie: Calibri, sans-serif; lățime: 800px; marja: auto;  a cursor: pointer; Culoarea albastra; text-decoration: nici unul;  tabel lățime: 100%;  table thead tr fundal: #ccc;  tabel tbody tr fundal: #ddd;  tabel tbody tr: nth-copil (2n + 1) fundal: #eee;  tabelul tr td: nth-child (1) text-align: center;  tabelul tr td: nth-copil (3), tabelul tr td: nth-child (4) text-align: right;  .error culoare: roșu; 

Acum, deschideți aplicația în browserul dvs. și aspectul ar trebui să fie centrat cu un font mai frumos în titlu:

Structura de bază a aplicației

Vom începe cu o declarație a modulului. Modulele în unghiulare sunt aproape același lucru ca în orice bibliotecă AMD, dar cu adăugarea de injecție de dependență, care este un lucru foarte util, după cum veți vedea. Iată declarația noastră aplicaţia modul:

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

Sintaxa este simplă - mai întâi se află numele modulului și apoi gama de dependențe - vom folosi doar ngRoute aici pentru a se ocupa de navigație, care va merge în continuare.

Routing

Rutarea este definită în module config () metodă:

app.config (funcția configure ($ routeProvider) 

Iată când injecția de dependență începe pentru prima dată - apelul nostru de apel va dura $ routeProvider ca singurul argument, iar acest modul va fi injectat de Angular.

Trebuie să vă asigurați că numele argumentului sunt exact identice cu numele modulelor, deoarece Angular le folosește pentru a se potrivi cu modulele corespunzătoare.

Acum să folosim de fapt $ routeProvider pentru a configura rutele:

$ routeProvider .when ('/ client /: id', controler: 'CustomerController', templateUrl: './templates/customers.html' ./templates/customer.html '). altfel (redirect:' / '); );

După cum puteți vedea pentru a defini o rută trebuie să apelați cand() metoda furnizorului (rețineți că pot fi înlănțuiți). 

Primul parametru este URI, iar al doilea este un obiect cu opțiuni pentru traseu. Aici, atașăm controale și șabloane adecvate pentru fiecare rută. În al doilea, de asemenea, folosim : id la sfârșit pentru a marca un parametru al traseului pe care îl vom folosi mai târziu. in caz contrar() metoda definește ce se va întâmpla dacă este accesat un alt URI.


Fabrică

Înainte de a scrie controlorii, trebuie să creăm un lucru numit fabrică. fabrică este o funcție care returnează un serviciu, care este util dacă doriți să separați funcțiile de obținere / setare de date de la controlorii (ceea ce este, desigur, ceea ce vreți să faceți întotdeauna). Îl definim folosind fabrică() metoda modulului:

app.factory ('Data', funcția Date ($ http) 

Primul parametru este numele serviciului, iar al doilea este o funcție care returnează serviciul care va fi creat utilizând această fabrică.

Vom folosi $ http modul pentru a accesa serverul nostru folosind Ajax. Acesta oferă metode de comenzi rapide pentru toate metodele HTTP și fiecare dintre ele întoarce o promisiune (dacă nu știți ce ar trebui să aruncați o privire aici și aici).

Trebuie să returnăm serviciul ca obiect cu toate metodele care vor fi folosite în controlerele noastre:

întoarcere 

Primul va OBȚINE toți clienții, astfel încât să le putem afișa într-o listă:

getCustomers: function getCustomers () return $ http.get ('/ clienți / toate'); ,

Al doilea va OBȚINE doar un singur client al lui id:

getCustomer: funcția getCustomer (id) retur $ http.get ('/ customers? id =' + id); ,

A treia voință POST cererea de a adăuga utilizator în baza de date:

addCustomer: funcția addCustomer (date) return $ http.post ('/ clienți', date); ,

Al doilea argument în $ Http.post () sunt datele care vor fi trimise serverului.

Următorul va ȘTERGE clientul cu id cu condiția:

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

Acum vor exista câteva tranzacții similare pentru tranzacții. Unul pentru a obține toate acestea:

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

Unul pentru a adăuga unul nou:

addTransaction: funcția addTransaction (date) return $ http.post ('/ transactions', data); ,

Și unul pentru a șterge:

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

Controlorul clientului

Controlerele din Angular sunt (cum sugerează și numele) o modalitate de a controla comportamentul aplicației. Vom avea unul pentru fiecare șablon. Mai întâi vom face una pentru pagina principală. Începeți prin definirea acesteia:

app.controller ('CustomersController', funcția CustomersController ($ scope, Data) 

Al doilea parametru este funcția constructorului pentru controler. Este primul argument (domeniul de aplicare $) este legătura dintre DOM și controler. Este inima legăturii bidirecționale a lui Angular. Al doilea este serviciul din fabrica pe care l-am creat mai devreme.

Obținerea listei

Acum vom primi lista clienților de la server utilizând serviciul nostru:

Data.getCustomers. () de succes (parseCustomers);

Toate promisiunile din Angular furnizează succes() și eroare() metode care pot fi utilizate pentru a adăuga apeluri corespunzătoare. Acum, să definim funcția care va analiza datele primite pentru ao afișa pe pagină:

 funcția parseCustomers (date) $ scope.customers = date; 

Da, asta este doar necesar pentru a alimenta șablonul cu date. Nu este nevoie de nici unul innerHTML/appendChild ()-codul ish.

Adăugarea de noi clienți

De asemenea, trebuie să oferim posibilitatea de a adăuga și de a elimina clienții. Mai întâi, să creăm un obiect în domeniul în care vom deține datele noului client:

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

În acest fel, putem evita accesarea DOM atunci când utilizatorul adaugă un client. Acum funcția care va adăuga clientul: 

$ scope.addCustomer = funcția addCustomer () 

Deoarece numele complet al utilizatorului va fi afișat în tabel, intrarea pentru acesta va fi aceeași, așa că trebuie să o împărțim pentru a obține numele și prenumele:

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

Acum numim funcția potrivită din fabrica noastră cu datele de la domeniul de aplicare $:

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

După care adăugăm ascultătorilor de succes și de eroare la promisiunea returnată:

.Succesul (customerAddSuccess) .error (customerAddError); 

Să definim mai întâi apelul de succes:

funcția clientAddSuccess (date)  

date argumentul conține textul răspunsului. Trebuie să clarificăm $ scope.error variabil:

$ scope.error = null;

Împingeți clientul nou adăugat la $ scope.customers:

$ Scope.customers.push (date);

Și setați $ scope.newCustomer la starea inițială pentru a elimina intrările:

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

Întoarcerea la eroare va seta doar $ scope.error variabilă la textul primit de la server:

funcția clientAddError (date) $ scope.error = date;  

Eliminarea clienților

Funcția de a elimina clientul va lua lui id ca parametru:

$ scope.removeCustomer = funcția removeCustomer (id) 

Vom afișa și o casetă de confirmare, astfel încât utilizatorul are șansa să anuleze acțiunea:

dacă (confirmați ("Chiar doriți să eliminați acest client?")) 

Dacă utilizatorul este sigur că dorește să continue, ștergem clientul:

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

Apelul de apel aici va trebui să elimine clientul $ scope.customers folosind id-ul obținut de pe server:

funcția clientRemoveSuccess (date) var i = $ scope.customers.length; în timp ce (i--) if ($ scope.customers [i] .id == date) $ scope.customers.splice (i, 1); 

Rezultatul

Codul complet ar trebui să arate astfel:

app.controller ('CustomersController', funcția CustomersController ($ scope, Data) Data.getCustomers () succes (parseCustomers); function parseCustomers (date) $ scope.newCustomer = name: ", nume de domeniu [nume] [nume] [nume] [nume] [nume] [nume] [nume] , e-mail: $ scope.newCustomer.email) .success (clientAddSuccess) .error (clientAddError); funcția clientAddSuccess (date) $ scope.error = null; $ scope.customers.push (data); $ scope.newCustomer = nume: ", email:"; funcția clientAddError (date) $ scope.error = date; $ scope.removeCustomer = function removeCustomer (id) if (confirmați " ?) Data.removeCustomer (id) .success (clientRemoveSuccess); funcția customerRemoveSuccess (date) var i = $ scope.customers.length; în timp ce (i--) if ($ scope.customers [i ] .id == date) $ scope.customers.splice (i, 1););

Template pentru clienți

Acum, pentru a arăta efectiv datele utilizatorilor noștri, trebuie să creăm un șablon. Am definit-o pe traseul care urmează să fie ./templates/customers.html, creați astfel publice / șabloane director și customers.html fișier în el.

Mai întâi adăugați titlul, astfel încât utilizatorul să știe unde este:

clienţii

Apoi avem nevoie de un tabel cu o poziție frumoasă pentru a afișa datele:

Acum adaugati tbody element. Și aici vine magia lui Angular. Utilizarea ng-repeat directivă îi spunem lui Angular să repete elementul:

Sintaxa este ca în JavaScript pentru ... in buclă. Acum putem accesa client pentru a obține toate datele de care avem nevoie. În versiunea Angular introduceți variabilele utilizând dublurile cotitură:

   Număr de înregistrare client   [-] client.first_name client.last_name   client.email  

Este deasemenea o ng-clic directivă care va acționa ca a onclick eveniment de apel invers, îl folosim pentru a adăuga abilitatea de a elimina clienții. În continuare există un subsol cu ​​intrări, astfel încât utilizatorul poate adăuga noi clienți:

    [+]  

Noi folosim ng model directive pentru a lega variabilele corespunzătoare de la domeniul de aplicare la intrările, astfel încât acestea să fie actualizate de fiecare dată când există o schimbare a valorii intrărilor.

Ultimul lucru pe care trebuie să-l faceți este să afișați un mesaj de eroare dacă există vreunul. Pentru a realiza acest lucru vom folosi ng-show directivă care va afișa elementul numai dacă expresia specificată este adevărată:

error

Asta e! Acum puteți deschide aplicația în browser și ar trebui să vedeți acest lucru:

Puteți adăuga un client nou făcând clic pe semnul plus din colțul din dreapta jos al tabelului.


Controlorul clientului

Acum, să creăm un controler pentru vizualizarea unui singur client:

app.controller ("CustomerController", funcția CustomerController ($ scope, $ routeParams, Data) 

Obținerea datelor

Noi folosim datele clientului $ routeParams care conține toți parametrii de traseu, cum ar fi : id am specificat mai devreme:

Data.getCustomer ($ routeParams.id) .success (parseCustomer); funcția parseCustomer (date) $ scope.customer = date; 

Callback-ul este aproape la fel ca în CustomersController. Acum să luăm toate tranzacțiile clientului:

Data.getTransactions ($ routeParams.id) .success (parseCustomersTransactions); funcția parseCustomersTransacții (date) $ scope.transactions = date; $ scope.sum = 0; pentru (var k în date) $ scope.sum + = parseFloat (date [k] .amount); 

Callback-ul este un pic diferit de ultimul, deoarece dorim să arătăm suma sumelor tranzacțiilor. Trebuie să folosim parseFloat () deoarece Laravel trimite flotoare ca șiruri de caractere.

Adăugarea de noi tranzacții

Codul va fi foarte similar cu cel utilizat pentru a crea noi clienți:

$ scope.newTransaction = nume: ", suma: 0; $ scope.addTransaction = funcția addTransaction () $ scope.newTransaction.customer_id = $ scope.customer.id; Data.addTransaction ($ scope.newTransaction) .success (transactionAddSuccess) .error (transactionAddError); funcția transactionAddSuccess (date) $ scope.error = null; data.amount = parseFloat (data.amount); $ scope.transactions.push (data); $ scope.sum + = date.amount; $ scope.newTransaction = nume: ", suma: 0;  funcția transactionAddError (date) $ scope.error = data; 

Singura diferență este faptul că adăugăm ID-ul clientului la date, astfel încât serverul să știe ce tranzacție este. Apelul de succes este, de asemenea, un pic modificat, deoarece trebuie să analizăm floatul înainte de al adăuga la domeniul de aplicare $ și trebuie să adăugăm suma la suma noastră.

Eliminarea tranzacțiilor

Codul pentru removeTransaction () funcția este aproape identică removeCustomer fiind diferită numai în numele variabilelor:

$ scope.removeTransaction = funcția removeTransaction (id) if (confirmați ('Chiar doriți să eliminați această tranzacție?')) Data.removeTransaction (id) .success (transactionRemoveSuccess);  funcția transactionRemoveSuccess (date) var i = $ scope.transactions.length; în timp ce (i--) if ($ scope.transactions [i] .id == date) $ scope.sum - = $ scope.transactions [i] .amount; $ scope.transactions.splice (i, 1); 

Rezultatul

Întregul controler ar trebui să arate astfel:

app.controller ("CustomerController", funcția CustomerController ($ scope, $ routeParams, Data) Data.getCustomer ($ routeParams.id) .success (parseCustomer); funcția parseCustomer (date) $ scope.customer = date; ($) $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ date [k] .amount); $ scope.newTransaction = nume: ", suma: 0; $ scope.addTransaction = funcția addTransaction () $ scope.newTransaction.customer_id = $ scope.customer.id; .addTransaction ($ scope.newTransaction) .success (transactionAddSuccess) .error (transactionAddError); funcția transactionAddSuccess (data) $ scope.error = null; data.amount = parseFloat (data.amount); $ scope.transactions.push (date); $ scope.sum + = data.amount; $ scope.newTransaction = nume: ", suma: 0; functie transactionAddError (date) $ scope.error = data; $ scope.removeTransaction = functi pe removeTransaction (id) if (confirmați ('Chiar doriți să eliminați această tranzacție?')) Data.removeTransaction (id) .success (transactionRemoveSuccess);  funcția transactionRemoveSuccess (date) var i = $ scope.transactions.length; în timp ce (i--) if ($ scope.transactions [i] .id == date) $ scope.sum - = $ scope.transactions [i] .amount; $ scope.transactions.splice (i, 1); );

Șablon client

Șablonul pentru un singur client nu are directive noi pentru Angular, așa că faceți doar un fișier numit customer.html în publice / template-uri / și plasați acest cod acolo:

Informații despre clienți

Nume: client.first_name client.last_name

E-mail: client.email

Listă de tranzacții

ID-ul Nume Cantitate Data
ID-ul de tranzacție [-] numele tranzacției $ transaction.amount.toFixed (2) transaction.created_at
[+]
Sumă:$ sum.toFixed (2)

error

Rețineți că folosim toFixed (2) pentru a rotunji flotoarele astfel încât să aibă doar două câmpuri zecimale, deoarece modul în care Laravel se ocupă cu flotoare în JSON.

Acum puteți deschide browserul și faceți clic pe unul dintre clienții pe care i-ați creat. Ar trebui să vedeți controlerul și șablonul în acțiune:


Concluzie

Acum, dacă ați adăugat unele funcționalități după prima parte, inclusiv în partea frontală ar trebui să fie o chestiune de adăugare a câtorva rânduri de cod aici și acolo.

Sper că după ce ați citit articolul și aplicația dvs. este terminată și funcționează, veți începe să vă gândiți cum puteți crea aplicații de o singură pagină fără AngularJS și orice aplicații PHP fără Laravel. Anunță-mă dacă ai avut probleme cu oricare dintre cadrele prezentate aici.

Cod