ProgHelp

Une communauté intelligente et active

[NodeJs & AngularJs] Tchat multi-client partie 2

Message par Wordeur » 18 Avril 2017, 10:32

Bonjour les amis !
J'espère que la première partit vous à plus (si oui) sinon, vous ne seriez sûrement pas la , nous allons voir le fonctionnement de notre client..
Il n'y a aucun CSS ( à vous de le créer au besoin)


Aujourd'hui, plusieurs notions seront abordé.
- Comment travaillé simultanément avec NodeJs & AngularJs
- [AngularJs] Le fonctionnement du data-binding.
- [AngularJs] Comment rafraîchirent notre $scope
SPOILER : AFFICHER
Si vous ne savez pas ce qu'est le scope https://docs.angularjs.org/tutorial/step_02

- [AngularJs] Comment dynamiser sont html.
- [NodeJs/Socket.IO] Comment se connecter au serveur.
- [NodeJs/Socket.IO] Comment envoyer et récupérer des informations avec le serveur.

Sans plus attendre le CLIENT (partie JS)!
var app = angular.module('app', []);
app.controller('appController', function appController($q,$scope) {

//On se connecter sur le serveur.
var socket = io('http://localhost:8080');

$scope.pseudo = "";
$scope.isConfigure = false;
$scope.resultat = "";
$scope.publicMessages = new Array();
$scope.conversationArray = new Array();
$scope.usersArray = new Array();
$scope.userSelected = "";

$scope.getActualisation = function(){
socket.emit('getUsers',true);
}

//Méthode de configuration du pseudo de l'utilisateur.
$scope.pseudoConfiguration = function(pseudoName){
//Si le pseudo de l'utilisateur est au format souhaité.
if(pseudoName !== undefined && pseudoName !== ""){
// Se référer à mon tutoriel sur les promises pour ceux qui ont du mal avec cette syntaxe.
request('pseudo',pseudoName).then(function(data){
/* data nous retourne true (réponse du serveur) si les données ont correctement été configurer,
et que la configuration du pseudo n'as pas étais configurer,
j'ai donc pris la décision ici que dans ce logiciel il n'y aurait qu'une configuration du pseudo
a vous de modifié a votre grès si cela ne vous convient pas. ^^. */
$scope.isConfigure = data;

// Si c'est configuré.
if($scope.isConfigure === true){
$scope.resultat = "Pseudo configurer";
// Nous demandons la listedes utilisateurs présents sur le tchat.
socket.emit('getUsers',true);
// On enregistre le nouveau pseudo de cet utilisateur.
$scope.pseudo = pseudoName;
}else{
// On affiche un message d'erreur.
$scope.resultat = "Erreur lors de la configuration du pseudo..";
}
});
}
}

// Fonction qui envoie un message public.
$scope.sendPublicMessage = function(){
// On envoie simplement le message.
// pas besoin d'envoyé le nom de l'utilisateur courant il est déja stocké sur le serveur ;)/
socket.emit('publicMessage',$scope.message);
}

// Simple fonction pour "optimiser" un minimum le rendu graphique..
$scope.switchIsActive = function(user){
// Variable qui affiche ou non une conversation.
user.isActive = !user.isActive;
// On défini l'utilisateur avec qui l'ont dialogue en privé actuellement.
$scope.userSelected = user;
}


// Fonction pour obtenir une conversation à partir d'un nom d'utilisateur.
$scope.getConversationFromUserName = function(userName){
// On créer un tableau de conversation.
var dataConversation = new Array();
// Pour chaque conversation enregistrée.
for(var i = 0 ; i < $scope.conversationArray.length; i++){
// Si l'utilisateur souhaité appartient à une conversation.
if($scope.conversationArray[i].person1 === userName|| $scope.conversationArray[i].person2 === userName){
dataConversation = $scope.conversationArray[i].stockConversation;
}
}
// On retourne cette conversation.
return dataConversation;
}

$scope.sendPrivateMessage = function(userMessage){
// On crée un objet comportant le pseudonyme de l'utilisateur et le message.
var data = {
pseudo: $scope.userSelected.pseudo,
message: userMessage
};
// On envoie le message.
socket.emit('privateCommunication',data);
}

// On s'abonne à l'événement 'getUsers' .
socket.on('getUsers',function(res){
// On réinitialise le tableau $scope.usersArray.
$scope.usersArray = new Array();
for(var i = 0 ; i < res.length ; i++){
var myUser = {
isActived : false,
pseudo : res[i]
};

$scope.usersArray.push(myUser);
}

$scope.$apply();
});

// Fonction qui reçoit tous les messages publics.
socket.on('publicMessage',function(res){
//On ajoute les données.
$scope.publicMessages.push(res);
// On actualise le $scope.
// L'actualisation du $scope est impérative sinon le ng-repeat ne se relancera
// Que lors de la prochaine interaction entre l'IHM et l'utilisateur...
$scope.$apply();
});

socket.on('privateCommunication',function(res){

// Pour chaque conversation.
// Si une conversation a pour émetteur ou recepteur res.recepteur || res.emeteur.
// on stock le message reçu dans cette conversation.
var isExist = false;
for(var i = 0 ; i < $scope.conversationArray.length; i++){
if($scope.conversationArray[i].person1 === res.emetteur && $scope.conversationArray[i].person2 === res.recepteur){
$scope.conversationArray[i].stockConversation.push(res.message);
isExist = true;
}else if($scope.conversationArray[i].person2 === res.emetteur &&$scope.conversationArray[i].person1 === res.recepteur){
$scope.conversationArray[i].stockConversation.push(res.message);
isExist = true;
}
}

// Sinon, nous créons une conversation..
if(isExist === false){
// Si cette conversation n'existe pas, nous la créons.
console.log("Conversation non existante : Creation");
var dataCommunication = {
stockConversation : new Array(),
person1 : res.emetteur,
person2 : res.recepteur
};

// On l'ajoute dans notre tableau de conversation.
$scope.conversationArray.push(dataCommunication);
}

// On refresh notre $scope.
$scope.$apply();
})

// Fonction qui envoie de manière asynchrone une requête au serveur socket.
function request(event, data){
var asyncPromise = $q.defer();

socket.emit(event, data);
socket.on(event, function(d) {
socket.off(event);
asyncPromise.resolve(d);
});

return asyncPromise.promise;
}

});


CLIENT partie HTML
<html ng-app="app">
<head>
<title>Tutoriel client to client NodeJs pour Proghelp</title>
<!-- On charge AngularJs et le module Socket.IO (pour interargir avec le serveur..)-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="/socket.io/socket.io.js"></script>

<script>
// Mettre le code Client js ici.
</script>

</head>

<body ng-controller="appController">

<div ng-show="!isConfigure">
<input ng-model="pseudoName"></input>
<button ng-click="pseudoConfiguration(pseudoName)">Valider</button>

</div>

<div ng-show="isConfigure">
<p>{{resultat}} [{{pseudo}}]</p>

<div ng-repeat="element in publicMessages track by $index">
<p>{{element}}</p>
</div>

<input ng-model="message"></input>
<button ng-click="sendPublicMessage()">Envoyer le message public</button>

</br><h1>Créer une conversation</h1>
Choix de l'utilisateur
</br>

<div ng-repeat="user in usersArray track by $index">
<div ng-show="user.pseudo != pseudo">
<button ng-click="switchIsActive(user)">{{user.pseudo}}</button>
<div ng-show="user.isActive">
<!-- Pour chaque message dans la conversation entre les deux utilisateurs. -->
<div ng-repeat="messageConversation in getConversationFromUserName(user.pseudo) track by $index">
{{messageConversation}}
</div>
<input ng-model="privateMessage"></input> <button ng-click="sendPrivateMessage(privateMessage)">Envoyer le message</button>
</div>
</div>
</div>

</div>

</body>
</html>


SPOILER : AFFICHER
Ps : Je n'ai pas réussi à exporté le code JS voila pourquoi il ce situe dans l'index, si quelqu'un à une solution je mettrais à jour le tutoriel afin de le rendre plus "propre" ^^


J'ai laissé volontairement dans ce tutoriel de nombreuses voies d'optimisation. Mon but premier dans ce cas est de vous apporter une manière de faire et non de vous donner une solution toute prémâchée dans la bouche , par exemple, vous pouvez voir que MALHEUREUSEMENT mon script ne fonctionnerait pas s'il y avait deux utilisateurs nommés Wordeur par exemple. Je vous laisse faire les modifications nécessaires
SPOILER : AFFICHER
Un indice chaque client possède dans son socket un identifiant unique :)
Pour en savoir plus : https://socket.io/docs/client-api/#socket/
.
Bonne journée les amis !
Les chaussettes de l'archiduchesse sont-elles sèches? Archi-sèches ?


Coordialement , Wordeur =)
Wordeur
Membre habitué
 
Messages : 69
Points d'honneur : 57 PH
Inscription : 28 Juin 2013

Message par Patak » 19 Avril 2017, 16:26

Sympa comme tuto !
Ton code a l'air propre en plus ! :grin:

+15 PH
Image


SPOILER : AFFICHER


Avatar de l’utilisateur
Patak
Administrateur
 
Messages : 1143
Points d'honneur : -666 PH
Inscription : 30 Oct 2012


Retour vers Langages du Web

cron
  • Qui est en ligne ?
  • Consulter les nouveaux messages
  • Consulter les messages sans réponse
  • Au total, il y a 1 utilisateur en ligne :: 0 inscrit, 0 invisible et 1 invité (basé sur le nombre d’utilisateurs actifs des 5 dernières minutes)
  • Le nombre maximum d’utilisateurs en ligne simultanément a été de 272 le 12 Mars 2015, 03:11
  • Utilisateur(s) parcourant ce forum : Aucun utilisateur inscrit et 1 invité