در قسمت قبل توانستیم دکمه Cancel edit را به برنامه اضافه کنیم و همچنین کل برنامه را به حالت ویرایش ببریم تا کلاس هایی از آن تغییر کند. در این قسمت باید این کدها را تکمیل کنیم اما قبل از شروع جلسه دوست دارم یک باگ مهم در برنامه را رفع کنیم. در حال حاضر اگر بدون اینکه درون فیلدهای فرم چیزی بنویسید، می توانید با کلیک روی post it یک پست جدید را ثبت کنید. یعنی پستی که نه عنوان دارد و نه متن!
قطعا چنین حالتی قابل قبول نیست بنابراین به فایل app.js رفته و متد submitPost را پیدا کنید. در این متد باید یک شرط if داشته باشیم تا اگر مقادیر عنوان و بدنه پست خالی بودند، اجازه ثبت پست داده نشود:
// Submit Post function submitPost() { const title = document.querySelector('#title').value; const body = document.querySelector('#body').value; const data = { title, body } // Validate input if (title === '' || body === '') { ui.showAlert('Please fill in all fields', 'alert alert-danger'); } else { // Create Post http.post('http://localhost:3000/posts', data) .then(data => { ui.showAlert('Post added', 'alert alert-success'); ui.clearFields(); getPosts(); }) .catch(err => console.log(err)); } }
یعنی اگر یکی دو از فیلد عنوان و متن خالی بود، یک alert نمایش داده شود که الزامی بودن این فیلدها را به کاربر اعلام کند. در غیر این صورت یعنی هر دو فیلد خالی نیستند و می توانیم کدهای درخواست post را در این قسمت قرار دهیم.
حالا که این باگ را تصحیح کرده ایم باید یک Event-listener را برای دکمه cancel edit تعریف کنیم تا هنگام کلیک روی آن، برنامه از حالت edit خارج و به حالت add برگردد. این کار در همین فایل app.js و در کنار دیگر event-listener ها انجام می شود:
// Listen for edit state document.querySelector('#posts').addEventListener('click', enableEdit); // Listen for cancel document.querySelector('.card-form').addEventListener('click', cancelEdit);
توجه داشته باشید که دکمه cancel از قبل وجود ندارد باید مثل من از event delegation استفاده کنید، در غیر این صورت به خطا برخواهید خورد. حالا باید متد cancelEdit را تعریف کنیم. من این متد را در انتهای فایل App.js تعریف می کنم:
// Cancel Edit State function cancelEdit(e) { if(e.target.classList.contains('post-cancel')) { ui.changeFormState('add'); } e.preventDefault(); }
از آنجا که از event delegation استفاده کرده ام باید از e.target برای تشخیص هدف خود کمک بگیریم. حالا اگر target ما دارای کلاسی به نام post-cancel بود یعنی دکمه cancel edit نمایش داده شده است و بر همین اساس changeFormState را صدا می زنیم تا برنامه به حالت add برگردد. مثل همیشه و محض احتیاط از preventDefault نیز استفاده کرده ایم تا رفتار پیش فرض مرورگر را متوقف کنیم. اگر یادتان باشد قسمت add در متد chageFormState را در جلسه قبل و به شکل زیر نوشتیم:
// بقیه کدها // } else { this.postSubmit.textContent = 'Post It'; this.postSubmit.className = 'post-submit btn btn-primary btn-block'; // Remove cancel btn if it is there if(document.querySelector('.post-cancel')) { document.querySelector('.post-cancel').remove(); } // Clear ID from hidden field this.clearIdInput(); // Clear text this.clearFields(); } }
بنابراین در اینجا گفته ایم که دکمه post it و کلاس هایش را به حالت اولیه برگرداند و سپس دکمه cancel edit را حذف کند. در مرحله بعد باید متد های clearIdInput و clearFields را صدا بزنیم تا به ترتیب برای ویرایش های بعد آماده شده و همچنین ظاهر فرم را تمیز نگه داریم.
همانطور که متوجه شدید تغییر state کلی برنامه کار نسبتا زمان گیری بود اما ویرایش پست ها که تنها کار باقی مانده است، از بقیه اجزاء برنامه آسان تر می باشد. در قدم اول به متد submitPost بروید. ما در این متد یک شرط if برای اعتبارسنجی (خالی نبودن فیلدها) تعریف کرده بودیم و می توانیم از همان شرط برای ویرایش نیز استفاده کنیم. ما می توانیم value همان فیلد مخفی را در فایل HTML چک کنیم تا بفهمیم برنامه در حالت ویرایش است یا حالت اضافه کردن پست:
// Submit Post function submitPost() { const title = document.querySelector('#title').value; const body = document.querySelector('#body').value; const id = document.querySelector('#id').value; const data = { title, body } // Validate input if(title === '' || body === '') { ui.showAlert('Please fill in all fields', 'alert alert-danger'); } else { // Check for ID if(id === '') { // Create Post http.post('http://localhost:3000/posts', data) .then(data => { ui.showAlert('Post added', 'alert alert-success'); ui.clearFields(); getPosts(); }) .catch(err => console.log(err)); } else { // Update Post } } }
در ابتدا متغیر id را تعریف کرده ام (id این عنصر برابر id بود بنابراین کافی است id# را هدف بگیریم). سپس یک شرط if دیگر درون حالت Else اضافه کرده ام تا id (فیلد مخفی ما) را چک کند. اگر این فیلد خالی بود یعنی در حالت ویرایش نیستیم بنابراین می توانیم کدهای اضافه کردن پست جدید را در این قسمت قرار دهیم اما اگر فیلد خالی نباشد (حالا هر مقداری که بخواهد، داشته باشد) یعنی در حالت ویرایش هستیم بنابراین با کلیک روی این دکمه باید عملیات ویرایش را انجام دهیم.
نوشتن درخواست ویرایش نیز دقیقا مانند درخواست ثبت پست جدید است و تفاوت های ریزی دارد. من این کد را یکجا برایتان قرار می دهم:
// بقیه کدها // // Validate input if(title === '' || body === '') { ui.showAlert('Please fill in all fields', 'alert alert-danger'); } else { // Check for ID if(id === '') { // Create Post http.post('http://localhost:3000/posts', data) .then(data => { ui.showAlert('Post added', 'alert alert-success'); ui.clearFields(); getPosts(); }) .catch(err => console.log(err)); } else { // Update Post http.put(`http://localhost:3000/posts/${id}`, data) .then(data => { ui.showAlert('Post updated', 'alert alert-success'); ui.changeFormState('add'); getPosts(); }) .catch(err => console.log(err)); } }
به جای درخواست post یک درخواست put را ارسال کرده ایم. برای این نوع از درخواست باید id پست در حال ویرایش را نیز ارسال کنیم که کرده ایم. سپس با showAlert به کاربر گفته ایم که پست او ویرایش و به روز رسانی شده است و نهایتا با استفاده از changeFormState حالت برنامه را از ویرایش خارج و به add برگردانده ایم. خود متد changeFormState متد clearFields را صدا می زد بنابراین نیازی نیست آن را جداگانه صدا بزنیم. در نهایت با صدا زدن getPosts پست های نمایش داده شده به کاربر را به روز رسانی می کنیم.
حالا پروژه ما تکمیل شده است. اگر می خواهید از این پروژه برای سرور خودتان خروجی بگیرید (babel کدهایتان را کامپایل می کند)، در ترمینال دستور زیر را تایپ کنید:
npm run build
با اجرای این دستور یک پوشه به نام build برایتان ایجاد می شود که حاوی فایلی به نام app.bundle.js است. این فایل تمام سورس کد شما به صورت یکجا (فایل های app.js و ui.js و http.js) است. ادغام کردن تمام کدها در یک فایل باعث کم شدن تعداد درخواست ها به سرور شده و سایت شما را سریع تر می کند.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.