Construire votre démarrage Formulaires Ajax dynamiques pour la planification

Ce que vous allez créer

Ce tutoriel fait partie de la Construire votre démarrage avec la série PHP sur Envato Tuts +. Dans cette série, je vous guide dans le lancement d’une startup du concept à la réalité en utilisant mes Planificateur de réunion application comme exemple de la vie réelle. À chaque étape du processus, je publierai le code de Meeting Planner sous forme d’exemples open source à partir desquels vous pourrez apprendre. Je traiterai également les problèmes liés au démarrage au fur et à mesure qu'ils surviennent.

introduction

Dans le tutoriel d'aujourd'hui, je vais vous guider à travers le jeu initial de modifications complètes à l'interface de planification de réunions. Mon objectif était d'utiliser Ajax pour rendre possibles toutes les activités de planification courantes sans aucune actualisation de page. Certains aspects se sont révélés simples et d’autres assez compliqués. Dans cet épisode, je vais me concentrer sur les parties les plus simples: comment construire des requêtes Ajax UX dans votre application Yii basée sur PHP.

Dans la deuxième partie, je couvrirai le plus difficile des problèmes de débogage Ajax et de la réinitialisation des widgets Bootstrap après le chargement initial de la page. Je vais également expliquer comment j'ai utilisé la console de développement du navigateur Google Chrome pour m'aider à identifier le code défectueux..

Franchement, bien que les mises à jour initiales se soient bien déroulées, je me suis heurté à tellement d'obstacles et de difficultés qu'il a parfois fallu abandonner l'objectif de la version bêta.. 

Bizarrement, il y aurait des chemins de code qui semblaient me rapprocher de l'achèvement et qui ensuite se heurtaient à un obstacle insurmontable - et il faudrait que je recommence avec une nouvelle approche. En fin de compte, j’ai pu mener à bien la planification complète via Ajax pour la version bêta..

Suivez-moi aujourd'hui pendant que je vous guide dans l'essentiel du travail.

Si vous n'avez pas encore essayé Meeting Planner, planifiez votre première réunion avec les nouvelles fonctionnalités interactives. Je participe aux commentaires ci-dessous, alors dites-moi ce que vous en pensez! Vous pouvez également me joindre sur Twitter @reifman. Je suis particulièrement intéressé si vous souhaitez suggérer de nouvelles fonctionnalités ou de nouveaux sujets pour de futurs tutoriels..

Pour rappel, tout le code pour Meeting Planner est écrit dans le framework Yii2 pour PHP. Si vous souhaitez en savoir plus sur Yii2, consultez notre série parallèle Programmer avec Yii2.

Rationaliser l'UX de planification

Mon objectif principal pour cette étape du produit était de mettre en œuvre toutes les fonctionnalités de planification clés avec Ajax et d'éliminer les actualisations de page actuellement requises pour modifier le sujet, ajouter des participants, ajouter des dates, des lieux et des notes..

Contexte

Comme j'avais déjà construit un peu d'Ajax sur le site, j'avais quelques idées sur ce qui irait bien et ce qui serait difficile.. 

Rejoignez-moi alors que je parcours les premiers éléments de la planification ajaxifying.

Modification du sujet de la réunion

J'ai commencé par modifier le panneau de sujet de la réunion, car il se compose de deux champs statiques, une entrée et une zone de texte. Cependant, le champ objet utilise un widget jQuery Typeahead. Les widgets peuvent compliquer les choses car vous devez être capable de les initialiser avec Ajax à l'esprit.

Dans ce cas, je précharge le formulaire masqué et charge la bibliothèque de widgets avec. Il n'y a pas de réelle complexité à cela. Dans le prochain épisode, vous verrez que le widget Commutateur Bootstrap sur les panneaux de date, heure et lieu rend la tâche beaucoup plus difficile..

Préchargement de tout le JavaScript

Donc, pour simplifier l'ajustement de chaque panneau de planification (participants, sujet, dates, lieux et notes), je les chargerais à l'avance et développerais le contenu initial de meeting.js.

J'ai également étendu la définition de MeetingAsset.php pour inclure davantage de JavaScript:

MeetingAsset est chargé par le fichier Meeting view.php:

Chargement du panneau de sujet

Le sujet et les détails de la réunion font partie du partiel _panel_what.php. Ci-dessous, je le configure pour qu'il soit masqué lors du chargement #editWhat:

has_subject || $ model-> subject == \ frontend \ models \ Meeting :: DEFAULT_SUBJECT) ?> 
message)) echo Html :: encode ($ this-> titre); // remarque: obligatoire car ne pouvant empêcher un espace supplémentaire else echo Html :: encode ($ this-> title). ':' .Html :: encode ($ modèle-> message). ' '; ?>
render ('_ form', ['modèle' => $ modèle, 'sujets' => $ modèle-> defaultSubjectList (),])?>

J'ai accroché le bouton d'édition (avec l'icône représentant un crayon) dans _panel_what.php pour appeler un JavaScript montrer ce que() bascule la fonction pour afficher ou masquer le formulaire de modification. Voici ce code:

isOrganizer () && $ model-> status <= Meeting::STATUS_CONFIRMED)  //['update', 'id' => $ model-> id] echo Html :: a (", 'javascript: void (0);', ['class' => 'btn btn-primaire glyphicon glyphicon-pencil', 'title' => 'Modifier', 'onclick' => 'showWhat ();']);?> 

le montrer ce que() La fonction meeting.js est affichée ci-dessous:

// affiche le message en haut de quelle fonction du panneau de sujet showWhat () if ($ ('# showWhat'). hasClass ("hidden")) $ ('# showWhat'). removeClass ("hidden"); $ ('# editWhat'). addClass ("caché");  else $ ('# showWhat'). addClass ("hidden"); $ ('# editWhat'). removeClass ("hidden"); $ ('# meeting-subject'). select (); ; function cancelWhat () showWhat (); 

Voici la partie supérieure de /frontend/views/meeting/_form.php qu'il cache et affiche. C'est ici que les champs de saisie et textarea apparaissent:

 
field ($ model, 'subject') -> widget (TypeaheadBasic :: classname (), ['data' => $ sujets, 'options' => ['placeholder' => Yii :: t ('frontend', ' quel est le sujet de cette réunion? '),' id '=>' sujet-réunion ', //' classe '=>' contrôle de formulaire en entrée large]], 'pluginOptions' => ['surligner' => vrai],]); ?>

Mise à jour du sujet et des détails de la réunion via Ajax

Lorsque l'utilisateur met à jour le formulaire de réunion, le nom Ajax suivant est appelé:

// fonction de groupe de sujets de réunion updateWhat (id) // ajax soumet sujet et message $ .ajax (url: $ ('# url_prefix'). val () + '/ meeting / updatewhat', données: id: id , sujet: $ ('# réunion-sujet'). val (), message: $ ('# réunion-message'). val (), succès: fonction (données) $ ('# showWhat'). text ($ ('# meeting-subject'). val ()); showWhat ();); 

La fonction actionUpdatewhat est dans MeetingController.php:

 fonction publique actionUpdatewhat ($ id, $ subject = ", $ message =") Yii :: $ app-> réponse-> format = \ yii \ web \ Response :: FORMAT_JSON; if (! Meeting :: isAttendee ($ id, Yii :: $ app-> user-> getId ())) return false;  $ m = Meeting :: findOne ($ id); $ m-> subject = $ subject; $ m-> message = $ message; $ m-> update (); retourne vrai;  

Remarquer Yii :: $ app-> response-> format = \ yii \ web \ Response :: FORMAT_JSON; qui configure une méthode Yii pour renvoyer JSON, pas HTML. 

Également Réunion: isAttendee () fonction est une vérification d'authentification pour s'assurer que l'utilisateur connecté est un participant avant de mettre à jour les données de la réunion.

Qu'ai-je appris jusqu'à présent

Comme vous pouvez le constater, il faut pas mal de code pour ajaxifier toutes ces pièces. 

L'un des défis est d'être humain, essayant de basculer entre autant de fichiers en même temps et deux langues différentes. PHP et JavaScript ont différentes façons de faire les choses. Par exemple, la concaténation de chaînes se fait avec une période en PHP et un signe plus en JavaScript. Changer rapidement de langue en essayant occasionnellement de construire des chaînes de paramètres de requête peut entraîner des erreurs.

Il existe également un besoin de contrôles de sécurité intensifs au sein de mes fonctions Ajax basées sur PHP. Dans le tutoriel d'aujourd'hui, vous voyez le début de ceci, mais je vais devoir faire des vérifications plus approfondies avant de rendre le code pleinement vivant..

Et finalement, au fur et à mesure, j'ai essayé de réutiliser des notations et des approches structurelles afin que tout le code ait une composition et une terminologie similaires, malgré le travail avec des éléments de données différents..

Envoi de notes de réunion

Les notes de réunion sont également des champs textarea statiques. Toutefois, il peut y avoir un fil de notes en cours qui doivent être mises à jour sur la page lorsque vous en ajoutez une (par exemple, pas un seul sujet de réunion). Et il est important de dire à l'utilisateur que nous informerons les participants de la note.

Par exemple, j'ai éliminé le bouton d'envoi UX dans la planification afin que la planification soit rapide et efficace. Cela confond souvent les utilisateurs de Meeting Planner, c'est pourquoi j'ai ajouté des alertes pour leur faire savoir que nous nous en occuperons..

Coder les notes via Ajax

Premièrement, il y a le _panel.php pour la note de réunion. Je pré-construit des alertes d'erreur cachées qui peuvent être affichées via jQuery selon les besoins. Je prévois de simplifier et de normaliser cela à l'avenir, notamment en facilitant l'utilisation de la localisation pour les messages..

Dans l'exemple ci-dessous, les deux noteMessage1 et noteMessage2 sont chargés comme cachés.

 

'btn btn-primaire glyphicon glyphicon-plus', 'title' => 'Modifier', 'onclick' => 'showNote ();')); ?>
render ('_ form', ['model' => $ model,])?>
render ('_ thread', ['model' => $ model, 'noteProvider' => $ noteProvider,])?>

Voici le jQuery qui recherche une note vide, affiche une erreur appropriée ou soumet le contenu via Ajax pour demander une mise à jour du fil de note et affiche une alerte de réussite:

function updateNote (id) note = $ ('# réunion-note'). val (); if (note == ") displayAlert ('noteMessage', 'noteMessage2'); return false; // ajax soumettre le sujet et le message $ .ajax (url: $ ('# url_prefix'). val () + ' / meeting-note / updatenote ', données: id: id, note: note, succès: fonction (données) $ (' # editNote '). addClass ("caché"); $ (' # réunion-note ' ) .val ("); updateNoteThread (id); displayAlert ('noteMessage', 'noteMessage1'); renvoyer la valeur true; // à faire - le message d'erreur s'affiche;  function updateNoteThread (id) // ajax soumettre le sujet et le message $ .ajax (url: $ ('# url_prefix'). val () + '/ meeting-note / updatethread', données: id: id, type: 'GET', succès: fonction (données) $ ('# noteThread'). html (données); // données ['réponseTexte'], erreur: fonction (erreur) ); 

L’un des problèmes à résoudre concerne la gestion des erreurs dans Ajax. Ce n'est pas facile à faire et nécessite une architecture assez détaillée pour supporter cela - pour l'instant, je suis passé à autre chose sans gérer ce genre d'erreur.

Ici se trouve le displayAlert () Fonction JavaScript que j'ai réutilisée et développée pour tous les panneaux et leurs messages d'alerte:

 function displayAlert (alert_id, msg_id) // quelle boîte d'alerte, c'est-à-dire quel commutateur d'alerte de panneau (alert_id) case 'noteMessage': // quel msg affichera le commutateur (msg_id) case 'noteMessage1': $ ('# noteMessage1') .removeClass ('caché'); // partagera la note $ ('# noteMessage2'). addClass ('hidden'); $ ('# noteMessage'). removeClass ('hidden'). addClass ('alert-info'). removeClass ('alert-danger'); Pause; case 'noteMessage2': $ ('# noteMessage1'). addClass ('hidden'); $ ('# noteMessage2'). removeClass ('hidden'); // pas de note $ ('# noteMessage'). removeClass ('hidden'). removeClass ('alert-info'). addClass ('alert-danger'); Pause;  Pause; case 'participantMessage': // le msg à afficher $ ('# participantMessageTell'). addClass ('hidden'); // partagera la note $ ('# participantMessageError'). addClass ('hidden'); $ ('# participantMessageOnlyOne'). addClass ("hidden"); $ ('# participantMessageNoEmail'). addClass ("hidden"); switch (msg_id) case 'participantMessageTell': $ ('# participantMessageTell'). removeClass ('hidden'); // partagera la note $ ('# participantMessage'). removeClass ('hidden'). addClass ('alert-info'). removeClass ('alert-danger'); Pause; case 'participantMessageError': $ ('# participantMessageError'). removeClass ("hidden"); $ ('# participantMessage'). removeClass ("hidden"). removeClass ('alert-info'). addClass ('alert-danger'); Pause; case 'participantMessageNoEmail': $ ('# participantMessageNoEmail'). removeClass ("hidden"); $ ('# participantMessage'). removeClass ("hidden"). removeClass ('alert-info'). addClass ('alert-danger'); Pause; case 'participantMessageOnlyOne': $ ('# participantMessageOnlyOne'). removeClass ("hidden"); $ ('# participantMessage'). removeClass ("hidden"). removeClass ('alert-info'). addClass ('alert-danger'); Pause;  Pause; case 'placeMessage': // quel message afficher $ ('# placeMsg1'). addClass ('hidden'); // partagera la note $ ('# placeMsg2'). addClass ('hidden'); // partagera la note $ ('# placeMsg3'). addClass ('hidden'); // partagera le commutateur de notes (msg_id) case 'placeMsg1': $ ('# placeMsg1'). removeClass ('hidden'); // partagera la note $ ('# placeMessage'). removeClass ('hidden'). addClass ('alert-info'). removeClass ('alert-danger'); Pause; case 'placeMsg2': $ ('# placeMsg2'). removeClass ('hidden'); // partagera la note $ ('# placeMessage'). removeClass ('hidden'). removeClass ('alert-info'). addClass ('alert-danger'); Pause;  Pause; case 'timeMessage': // le message à afficher $ ('# timeMsg1'). addClass ('hidden'); // partagera la note $ ('# timeMsg2'). addClass ('hidden'); // partagera la note //$('#timeMsg3').addClass('hidden '); // partagera le commutateur de notes (msg_id) case 'timeMsg1': $ ('# timeMsg1'). removeClass ('hidden'); // partagera la note $ ('# timeMessage'). removeClass ('hidden'). addClass ('alert-info'). removeClass ('alert-danger'); Pause; case 'timeMsg2': $ ('# timeMsg2'). removeClass ('hidden'); // partagera la note $ ('# timeMessage'). removeClass ('hidden'). removeClass ('alert-info'). addClass ('alert-danger'); Pause;  Pause;  

Mise à jour du fil de notes

Lorsqu'un utilisateur envoie une nouvelle note, MeetingNoteController.php actionUpdatethread () s'appelle via Ajax. Voici le PHP:

fonction publique actionUpdatethread ($ id) Yii :: $ app-> réponse-> format = \ yii \ web \ Response :: FORMAT_JSON; $ m = Meeting :: findOne ($ id); $ noteProvider = new ActiveDataProvider (['query' => MeetingNote :: find () -> où (['meeting_id' => $ id]), 'sort' => ['defaultOrder' => ['created_at' => SORT_DESC]],]); $ result = $ this-> renderPartial ('_ thread', ['modèle' => $ m, 'noteProvider' => $ noteProvider,]); return $ result;  

J'ai parfois essayé de renvoyer simplement le dernier élément de contenu (c'est-à-dire la dernière note) et d'insérer au-dessus des éléments précédents. Cependant, cela s’est avéré gênant, en particulier avec les dates et les endroits qui apparaissent dans les lignes.

Pour l'instant, je remplace l'intégralité du fil de contenu mis à jour et le panneau complet via Ajax. Voici le partial _thread.php qui charge toutes les notes, y compris la nouvelle:

compte> 0):?>  $ timeProvider, 'layout' => 'items', 'itemView' => '_list',])?> 

J'espère que cela suffit pour étudier et essayer pour aujourd'hui.

J'ai littéralement passé environ cinq à sept longues journées de codage, y compris une nuit blanche à compléter tout le code derrière cet épisode et le prochain. Je n'avais pas passé la nuit blanche depuis des années. Pourtant, les résultats ont été inspirants.

Alors, quelle est la prochaine?

J'espère que les bases du développement Ajax pour Yii et PHP ont été utiles. J'ai certainement appris beaucoup de choses grâce à ce processus et les changements ont rendu la planification des réunions incroyablement plus rapide et plus simple qu'auparavant..

Dans le prochain épisode, je couvrirai les fonctionnalités restantes en ajoutant des dates et des lieux et en utilisant les outils de débogage de Google Chrome Browser pour m'aider..

Pendant que vous attendez le prochain épisode, planifiez votre première réunion et testez les fonctionnalités de planification Ajax. Aussi, je vous serais reconnaissant de partager votre expérience ci-dessous dans les commentaires, et vos suggestions m'intéresseront toujours. Vous pouvez également me joindre directement sur Twitter @reifman.

La version de prévisualisation de Meeting Planner est maintenant en ligne. Vous pouvez maintenant le partager avec vos amis et collègues pour utiliser.

Enfin, je commence à expérimenter avec WeFunder à partir de la mise en œuvre des nouvelles règles de la SEC en matière de financement participatif. Vous pouvez suivre notre profil ici si vous le souhaitez. Je vais aussi écrire plus à ce sujet dans un prochain tutoriel.

Surveillez les prochains tutoriels de la série Construire votre démarrage avec PHP.

Liens connexes

  • Planificateur de réunion
  • Page WeFunder de l'organisateur de réunions
  • Programmation avec Yii2: Mise en route
  • L'échange de développeurs Yii2