AngularJS et Laravel terminer la construction d'un CRM

Lors de la création d'une application d'une seule page, nous devrions utiliser une sorte de cadre pour effectuer une partie du travail pour nous afin de pouvoir nous concentrer sur les fonctionnalités réelles.. 

AngularJS convient parfaitement ici, car des fonctionnalités telles que l'injection de dépendance dynamique et la liaison de données bidirectionnelle sont tout simplement géniales. Parfois, nous avons également besoin d’une sorte de serveur. Si vous avez choisi PHP, alors Laravel peut être votre meilleure option, car il est facile de travailler avec et assez puissant.

Dans cette partie du didacticiel, nous allons construire le frontal de notre application en utilisant AngularJS. Angular est un cadre vraiment unique. Au lieu d’abréger le code HTML ou d’offrir un moyen de manipulation DOM, ils ont étendu le code HTML pour tenir compte du fait qu’il n’était sûrement pas conçu pour fonctionner avec des données dynamiques.. 

A cause de cela, Angular peut avoir besoin de plus d’apprentissage que d’autres frameworks, mais cela vaut vraiment la peine.


Préparation

Avant de commencer à programmer notre interface, nous devons modifier un peu la partie Laravel. Aller à app / vues, Supprimez l'exemple fourni et créez le fichier nommé. home.php. Maintenant, créons la mise en page. 

Commencez avec le DOCTYPE et le html étiquette:

 

Comme vous pouvez le constater, nous utilisons déjà des outils AngularJS - les ng-app directif. Cela indique à Angular d’utiliser le module nommé app pour cette application (nous le définirons plus tard). Après cela, ajoutez le tête avec un titre et CSS:

Gestion de la clientèle 

Maintenant vous pouvez mettre le scénario tags in avec Angular, son module de routage et notre application:

  

 Cette directive dit à Angular de mettre le modèle demandé dans cet élément.

Ensuite, il suffit d’ajouter une route pour afficher le modèle (en app / routes.php). Ajoutez ceci avant les routes pour les contrôleurs:

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

Maintenant, si vous démarrez le serveur (avec php artisan servir) vous devriez voir notre présentation de base lorsque vous accédez à http: // localhost: 8000 / dans votre navigateur:

Le style

Cet article ne se concentrera pas sur tout ce qui concerne les CSS, mais pour rendre l'application plus agréable à l'œil pendant le développement, nous allons lui ajouter du style. Aller au Publique/ répertoire de votre application (à côté de app /) et créer le style.css avec ce code dedans:

body font-family: Calibri, sans-serif; largeur: 800px; marge: auto;  un curseur: pointeur; Couleur bleue; texte-décoration: aucun;  table largeur: 100%;  table thead tr background: #ccc;  table tbody tr background: #ddd;  table tbody tr: n-enfant (2n + 1) background: #eee;  table tr td: nth-child (1) text-align: center;  table tr td: nth-enfant (3), table tr td: nth-enfant (4) text-align: right;  .error color: red; 

Maintenant, ouvrez l'application dans votre navigateur et la mise en page doit être centrée avec une police plus agréable dans l'en-tête:

Structure d'application de base

Nous allons commencer par une déclaration de module. Les modules dans Angular sont à peu près les mêmes que dans n'importe quelle bibliothèque AMD, mais avec l'ajout de l'injection de dépendance, ce qui est vraiment utile, comme vous le verrez. Voici la déclaration de notre app module:

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

La syntaxe est simple - commence par le nom du module, puis le tableau des dépendances - nous n'utiliserons que ngRoute ici pour gérer la navigation, qui ira ensuite.

Routage

Le routage est défini dans le module config () méthode:

app.config (fonction configure ($ routeProvider) 

C’est le moment où l’injection de dépendance s’installe pour la première fois - notre rappel prendra $ routeProvider comme seul argument, et ce module sera injecté par Angular.

Vous devez vous assurer que les noms des arguments sont exactement les mêmes que ceux des modules, car Angular les utilise pour faire correspondre les modules appropriés..

Maintenant, utilisons réellement le $ routeProvider pour configurer les itinéraires:

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

Comme vous pouvez le voir pour définir un itinéraire, vous devez appeler le quand() méthode du fournisseur (notez qu'ils peuvent être chaînés). 

Le premier paramètre est l'URI et le second est un objet avec les options de la route. Ici, nous attachons des contrôleurs et des modèles appropriés à chaque route. Dans le second on utilise aussi : id à la fin pour marquer un paramètre de route que nous utiliserons plus tard. le autrement() méthode définit ce qui se passera si un autre URI est accédé.


Usine

Avant d'écrire les contrôleurs, nous devons créer quelque chose appelé usine. usine est une fonction qui renvoie un service, ce qui est utile si vous souhaitez séparer les fonctions de récupération / configuration de données des contrôleurs (ce qui est bien sûr ce que vous voulez toujours faire). Nous le définissons en utilisant le usine() méthode du module:

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

Le premier paramètre est le nom du service et le second est une fonction qui renvoie le service qui sera créé avec cette fabrique..

Nous allons utiliser le $ http module pour accéder à notre serveur en utilisant Ajax. Il fournit des méthodes de raccourci pour toutes les méthodes HTTP et chacune d'elles renvoie une promesse (si vous ne savez pas ce que c'est, regardez ici et ici).

Nous devons renvoyer le service en tant qu'objet avec toutes les méthodes qui seront utilisées dans nos contrôleurs:

revenir 

Le premier sera OBTENIR tous les clients afin que nous puissions les montrer dans une liste:

getCustomers: function getCustomers () return $ http.get ('/ clients / tous'); ,

Deuxième volonté OBTENIR un seul client par son identifiant:

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

Troisième testament POSTER la demande pour ajouter l'utilisateur à la base de données:

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

Le deuxième argument de $ http.post () sont les données qui seront envoyées au serveur.

Le prochain sera EFFACER le client avec le identifiant à condition de:

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

Maintenant, il y aura peu de semblables pour les transactions. Un pour tous les obtenir:

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

Un pour en ajouter un nouveau:

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

Et un à supprimer:

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

Contrôleur Clients

Les contrôleurs dans Angular constituent (comme son nom l'indique) un moyen de contrôler le comportement de l'application. Nous en aurons un pour chaque modèle. Nous allons d’abord en créer un pour la page principale. Commencez par le définir:

app.controller ('CustomersController', fonction CustomersController ($ scope, Data) 

Le second paramètre est la fonction constructeur du contrôleur. C'est le premier argument ($ scope) est le lien entre le DOM et le contrôleur. C'est le cœur de la liaison de données bidirectionnelle d'Angular. Le second est le service de l'usine que nous avons créé précédemment.

Obtenir la liste

Maintenant, nous allons obtenir la liste des clients du serveur en utilisant notre service:

Data.getCustomers (). Success (parseCustomers);

Toutes les promesses dans Angular fournissent la Succès() et Erreur() méthodes qui peuvent être utilisées pour ajouter des rappels appropriés. Définissons maintenant la fonction qui analysera les données entrantes pour les afficher sur la page:

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

Oui, c'est tout ce qu'il faut pour alimenter le modèle avec des données. Pas besoin de tout innerHTML/appendChild ()-code ish.

Ajout de nouveaux clients

Nous devons également fournir la possibilité d'ajouter et de supprimer des clients. Commençons par créer un objet dans la portée où nous allons stocker les données du nouveau client:

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

De cette façon, nous pouvons éviter d'accéder à DOM lorsque l'utilisateur ajoute un client. Maintenant, la fonction qui va réellement ajouter le client: 

$ scope.addCustomer = function addCustomer () 

Puisque le nom complet de l'utilisateur sera affiché dans la table, l'entrée sera la même. Nous devons donc la scinder pour obtenir le prénom et le nom:

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

Maintenant, nous appelons la fonction appropriée de notre usine avec les données de $ scope:

Data.addCustomer (prénom: noms [0], dernier nom: noms [1], email: $ scope.newCustomer.email)

Après cela, nous ajoutons les écouteurs succès et erreurs à la promesse renvoyée:

.success (customerAddSuccess) .error (customerAddError); 

Définissons d'abord le rappel de succès:

fonction customerAddSuccess (data)  

le Les données L'argument contient le texte de la réponse. Nous devons effacer le $ scope.error variable:

$ scope.error = null;

Poussez le nouveau client ajouté à $ scope.customers:

$ scope.customers.push (data);

Et mettre $ scope.newCustomer à son état initial pour effacer les entrées:

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

Le rappel d'erreur ne fera que définir la $ scope.error variable au texte reçu du serveur:

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

Suppression des clients

La fonction pour supprimer le client prendra sa identifiant en paramètre:

$ scope.removeCustomer = fonction removeCustomer (id) 

Nous allons également afficher une boîte de confirmation afin que l'utilisateur puisse annuler l'action:

if (confirmez ('Voulez-vous vraiment supprimer ce client?')) 

Si l'utilisateur est sûr de vouloir continuer, nous supprimons le client:

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

Le rappel ici devra retirer le client de $ scope.customers en utilisant l'identifiant obtenu du serveur:

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

Le résultat

Le code complet devrait ressembler à ceci:

app.controller ('CustomersController', fonction CustomersController ($ scope, Data) Data.getCustomers (). success (parseCustomers); fonction parseCustomers (data) $ scope.customers = data; $ scope.newCustomer = name: ", email:"; $ scope.addCustomer = fonction addCustomer () noms var = = scope.newCustomer.name.split ("); Data.addCustomer (prénom: noms [0], dernier nom: noms [1] , email: $ scope.newCustomer.email) .success (customerAddSuccess) .error (customerAddError); fonction customerAddSuccess (data) $ scope.error = null; $ scope.customers.push (data); $ scope.newCustomer = name: ", email:"; function customerAddError (data) $ scope.error = data; $ scope.removeCustomer = function removeCustomer (id) if (confirm ('Voulez-vous vraiment supprimer ce client ? ')) Data.removeCustomer (id) .success (customerRemoveSuccess); fonction customerRemoveSuccess (données) var i = $ scope.customers.length; tandis que (i--) if ($ scope.customers [i ] .id == data) $ scope.customers.splice (i, 1););

Modèle de clients

Maintenant, pour montrer les données à nos utilisateurs, nous devons créer un modèle. Nous l'avons défini dans l'itinéraire comme étant ./templates/customers.html, alors créez le public / templates répertoire et le clients.html déposer dedans.

Ajoutez d’abord le titre pour que l’utilisateur sache où il se trouve:

Les clients

Ensuite, nous avons besoin d’un tableau avec un titre intéressant pour afficher les données:

Maintenant, ajoutez le tbody élément. Et voici où la magie d'Angular entre à nouveau. En utilisant le ng-répéter directive, nous demandons à Angular de répéter l'élément:

La syntaxe est la même que dans JavaScript pour… dans boucle. Maintenant nous pouvons accéder à la client variable pour obtenir toutes les données dont nous avons besoin. Dans Angular, vous insérez des variables à l'aide de doubles accolades:

   N ° de client   [-] customer.first_name customer.last_name    email client   

Il y a aussi ng-clic directive qui agira en tant que sur clic rappel d'événement, nous l'utilisons pour ajouter la possibilité de supprimer des clients. Ensuite, un pied de page avec des entrées permet à l'utilisateur d'ajouter de nouveaux clients:

    [+]  

Nous utilisons le ng-model directive pour lier les variables appropriées de la portée aux entrées, afin qu'elles soient mises à jour chaque fois qu'il y a un changement dans la valeur des entrées.

La dernière chose à faire est d'afficher un message d'erreur s'il y en a. Pour y parvenir, nous utiliserons ng-show directive qui ne montrera l'élément que si l'expression spécifiée est vraie:

Erreur

C'est tout! Maintenant, vous pouvez ouvrir l'application dans votre navigateur et vous devriez voir ceci:

Vous pouvez ajouter un nouveau client en cliquant sur le signe plus dans le coin inférieur droit du tableau..


Contrôleur Client

Créons maintenant un contrôleur pour une vue client unique:

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

Obtenir les données

Nous obtenons les données du client en utilisant $ routeParams module qui contient tous les paramètres de route comme le : id nous avons précisé plus tôt:

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

Le rappel est à peu près le même que dans le ClientsContrôleur. Maintenant, obtenons toutes les transactions du client:

Data.getTransactions ($ routeParams.id) .success (parseCustomersTransactions); fonction parseCustomersTransactions (data) $ scope.transactions = data; $ scope.sum = 0; for (var k dans les données) $ scope.sum + = parseFloat (data [k] .amount); 

Le rappel est un peu différent du dernier parce que nous voulons aussi montrer la somme des montants des transactions. Nous devons utiliser parseFloat () parce que Laravel envoie des flotteurs sous forme de chaînes.

Ajout de nouvelles transactions

Le code sera très similaire à celui utilisé pour créer de nouveaux clients:

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

La seule différence est que nous ajoutons l'identifiant du client aux données afin que le serveur sache de quelle transaction il s'agit. Le rappel de succès est aussi un peu modifié, car nous devons analyser le float avant de l’ajouter à la liste. $ scope et nous devons ajouter le montant à notre somme.

Supprimer des transactions

Le code pour removeTransaction () la fonction est presque identique à enleverClient n'étant différent que dans les noms de variables:

$ scope.removeTransaction = function removeTransaction (id) if (confirmer ('Voulez-vous vraiment supprimer cette transaction?')) Data.removeTransaction (id) .success (transactionRemoveSuccess);  fonction 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); 

Le résultat

Le contrôleur entier devrait ressembler à ceci:

app.controller ('CustomerController', fonction CustomerController ($ scope, $ routeParams, Data) Data.getCustomer ($ routeParams.id) .success (parseCustomer); fonction parseCustomer (data) $ scope.customer = data; Data .getTransactions ($ routeParams.id) .success (parseCustomersTransactions); fonction parseCustomersTransactions (data) $ scope.transactions = data; $ scope.sum = 0; pour (variable dans les données) $ scope.sum + = parseFloat ( data [k] .amount); $ scope.newTransaction = name: ", montant: 0; $ scope.addTransaction = fonction addTransaction () $ scope.newTransaction.customer_id = $ scope.customer.id; Data .addTransaction ($ scope.newTransaction) .success (transactionAddSuccess) .error (transactionAddError); fonction transactionAddSuccess (data) $ scope.error = null; data.amount = parseFloat (data.amount); $ scope.transactions.push (data); $ scope.sum + = data.amount; $ scope.newTransaction = name: ", montant: 0; function transactionAddError (data) $ scope.error = data; $ scope.removeTransaction = functi sur removeTransaction (id) if (confirm ('Voulez-vous vraiment supprimer cette transaction?')) Data.removeTransaction (id) .success (transactionRemoveSuccess);  fonction 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); );

Modèle de client

Le modèle pour un seul client n'a pas de nouvelle directive Angular. Créez donc un fichier nommé client.html dans public / templates / et placez ce code là:

informations concernant le client

Prénom: customer.first_name customer.last_name

Email: email client

Liste des transactions

ID prénom Montant Rendez-vous amoureux
identifiant de transaction [-] transaction.name $ transaction.amount.toFixed (2) transaction.created_at
[+]
Somme:$ sum.toFixed (2)

Erreur

Notez que nous utilisons toFixed (2) pour arrondir les flottants afin qu’ils ne disposent que de deux champs décimaux, car la manière dont Laravel gère les flottants dans JSON.

Maintenant, vous pouvez ouvrir le navigateur et cliquer sur l’un des clients que vous avez créé. Vous devriez voir le contrôleur et le modèle en action:


Conclusion

Maintenant, si vous avez ajouté des fonctionnalités après la première partie, l'inclure dans l'interface frontale devrait consister à ajouter quelques lignes de code ici et là..

J'espère qu'après avoir lu l'article et que votre application soit terminée et opérationnelle, vous commencerez à penser à la possibilité de créer des applications d'une seule page sans AngularJS ni aucune application PHP sans Laravel. Faites-moi savoir si vous avez des problèmes avec l'un des cadres présentés ici.