تا این قسمت از این سری آموزشی، بسیار خوب جلو رفته ایم و قسمت اصلی کار را پیاده سازی کرده ایم. حالا تنها جزئیات آن باقی مانده است. در این جلسه ابتدا با دکمه back و کارایی آن شروع می کنیم که کار بسیار ساده ای می باشد. برای شروع باید به کنترلر app برویم و یک event-listener دیگر ایجاد کنیم:
// بقیه کدها // // Edit icon click event document.querySelector(UISelectors.itemList).addEventListener('click', itemEditClick); // Update item event document.querySelector(UISelectors.updateBtn).addEventListener('click', itemUpdateSubmit); // Back button event document.querySelector(UISelectors.backBtn).addEventListener('click', UICtrl.clearEditState); }
تنها کاری که لازم بود انجام دهیم، صدا زدن متد clearEditState می باشد! مرحله بعد اضافه کردن یک event-listener دیگر برای حذف کردن آیتم ها است بنابراین:
// بقیه کدها // // Edit icon click event document.querySelector(UISelectors.itemList).addEventListener('click', itemEditClick); // Update item event document.querySelector(UISelectors.updateBtn).addEventListener('click', itemUpdateSubmit); // Delete item event document.querySelector(UISelectors.deleteBtn).addEventListener('click', itemDeleteSubmit); // Back button event document.querySelector(UISelectors.backBtn).addEventListener('click', UICtrl.clearEditState); }
متد itemDeleteSubmit که در کد بالا استفاده شده است، هنوز هیچ جایی از فایل ما تعریف نشده است بنابراین باید آن را تعریف کنیم. من این متد را در همان کنترلر app و پس از متد itemUpdateSubmit تعریف می کنم. در مرحله اول باید آیتم فعلی را دریافت کنیم تا بدانیم کدام آیتم را حذف کنیم:
// Delete button event const itemDeleteSubmit = function(e){ // Get current item const currentItem = ItemCtrl.getCurrentItem(); e.preventDefault(); }
مثل همیشه از preventDefault استفاده کرده ام تا ناهماهنگی در کدها نباشد. در مرحله بعد باید آیتم دریافت شده از getCurrentItem را بر اساس آیدی برگردانده شده از data structure حذف کنیم. این کار نیز ساده است:
// Delete button event const itemDeleteSubmit = function(e){ // Get current item const currentItem = ItemCtrl.getCurrentItem(); // Delete from data structure ItemCtrl.deleteItem(currentItem.id); e.preventDefault(); }
از آنجایی که هنوز متدی به نام deleteItem نداریم باید به کنترلر item ها برویم و پس از متد updateItem آن را تعریف کنیم:
deleteItem: function(id){ // Get ids const ids = data.items.map(function(item){ return item.id; }); // Get index const index = ids.indexOf(id); // Remove item data.items.splice(index, 1); }, clearAllItems: function(){ data.items = []; }
ما با استفاده از تابع map بین آیتم ها گردش کرده ایم و id تک تک آن ها را برمی گرداند. کار تابع map فیلتر کردن طبق تابع پاس داده شده به آن است، بنابراین چیزی شبیه به forEach است اما چیزی را در نهایت برمی گرداند. حالا تمام id های تمام آیتم ها درون ثابت ids می باشد. در مرحله بعد باید index مربوط به آیتم پاس داده شده را پیدا کنیم. این کار با indexOf انجام شده است. در نهایت نیز با استفاده از متد splice آن آیتم را از آرایه data.items حذف کرده ایم. این قسمت تکمیل شده است.
حالا دوباره به itemDeleteSubmit برگردید. کد بالا آیتم را از data structure حذف می کرد اما هنوز تغییرات ما درون UI قابل مشاهده نیست بنابراین می گوییم:
// Delete button event const itemDeleteSubmit = function(e){ // Get current item const currentItem = ItemCtrl.getCurrentItem(); // Delete from data structure ItemCtrl.deleteItem(currentItem.id); // Delete from UI UICtrl.deleteListItem(currentItem.id); e.preventDefault(); }
این متد (deleteListItem) نیز تعریف نشده است بنابراین به کنترلر UI می رویم و پس از updateListItem آن را تعریف می کنیم:
deleteListItem: function(id){ const itemID = `#item-${id}`; const item = document.querySelector(itemID); item.remove(); }
به همین سادگی می توانیم آیتم ها را حذف کنیم. در حال حاضر اگر به مرورگر بروید و این کد را تست کنید، قابلیت حذف آیتم ها به برنامه اضافه شده است. تنها مشکل اینجاست که پس از حذف آیتم مورد نظر از UI و data structure دیگر از حالت ویرایش خارج نمی شویم و تمام دکمه های Update Meal و Back و... هنوز نمایش داده می شوند. همچنین کالری کل نیز به روز رسانی نمی شود و روی مقدار قبلی باقی می ماند. اگر یادتان باشد در قسمت قبل دقیقا همین مشکل را داشتیم و با چند خط کد آن را حل کردیم. برای حل مشکل به itemDeleteSubmit برگردید و کدهای آن را تکمیل کنید:
// Delete button event const itemDeleteSubmit = function(e){ // Get current item const currentItem = ItemCtrl.getCurrentItem(); // Delete from data structure ItemCtrl.deleteItem(currentItem.id); // Delete from UI UICtrl.deleteListItem(currentItem.id); // Get total calories const totalCalories = ItemCtrl.getTotalCalories(); // Add total calories to UI UICtrl.showTotalCalories(totalCalories); UICtrl.clearEditState(); e.preventDefault(); }
دوباره چیزی که در جلسه قبل توضیح دادم را عینا توضیح می دهم. پس از صدا زدن deleteListItem و به روز رسانی آیتم ها، دوباره متد getTotalCalories را صدا زده ایم. باید یادتان باشد که این متد را در جلسات قبل نوشته ایم و کارش محاسبه تعداد کل کالری ها بود. با این حساب تعداد کل کالری ها (آپدیت شده) درون totalCalories قرار می گیرد. سپس showTotalCalories را صدا می زنیم تا مقدار کل کالری را در UI به روز رسانی کند. در نهایت اگر متد clearEditState را صدا بزنیم، از حالت ویرایش خارج می شویم. در ضمن این متد درون خودش متد پاک کردن فیلدها را نیز دارد بنابراین نیازی به پاکسازی جداگانه فیلد ها نداریم. حالا کدها بدون مشکل کار می کنند.
در مرحله بعد باید روی دکمه Clear All (قسمت بالا و سمت راست برنامه) کار کنیم. اگر کاربر روی این دکمه کلیک کند باید تمام آیتم ها یکجا حذف شوند. بنابراین قدم اول تعریف یک event-listener برای آن است:
// Update item event document.querySelector(UISelectors.updateBtn).addEventListener('click', itemUpdateSubmit); // Delete item event document.querySelector(UISelectors.deleteBtn).addEventListener('click', itemDeleteSubmit); // Back button event document.querySelector(UISelectors.backBtn).addEventListener('click', UICtrl.clearEditState); // Clear items event document.querySelector(UISelectors.clearBtn).addEventListener('click', clearAllItemsClick); }
حالا باید متد clearAllItemsClick را تعریف کنیم. البته یادتان نرود که clearBtn را نیز به مجموعه سلکتورهایتان اضافه کنید:
const UISelectors = { itemList: '#item-list', listItems: '#item-list li', addBtn: '.add-btn', updateBtn: '.update-btn', deleteBtn: '.delete-btn', backBtn: '.back-btn', clearBtn: '.clear-btn', itemNameInput: '#item-name', itemCaloriesInput: '#item-calories', totalCalories: '.total-calories' }
من متد clearAllItemsClick را پس از itemDeleteSubmit تعریف می کنم:
// Clear items event const clearAllItemsClick = function(){ // Delete all items from data structure ItemCtrl.clearAllItems(); }
ابتدا متدی به نام clearAllItems تمام آیتم های ما را حذف می کند. من این متد را درون کنترلر item و پس از deleteItem تعریف می کنم:
clearAllItems: function(){ data.items = []; }
یعنی آرایه data را خالی می کنیم. همچنین تابع دیگری به نام removeItems را نیز در کنترلر UI تعریف می کنیم تا آیتم ها را از UI نیز حذف کند:
removeItems: function(){ let listItems = document.querySelectorAll(UISelectors.listItems); // Turn Node list into array listItems = Array.from(listItems); listItems.forEach(function(item){ item.remove(); }); }
این کد را در جلسات قبل نیز دیده ایم، بنابراین چیز جدیدی برای توضیح ندارد. حالا می توانیم clearAllItemsClick را تکمیل کنیم:
// Clear items event const clearAllItemsClick = function(){ // Delete all items from data structure ItemCtrl.clearAllItems(); // Get total calories const totalCalories = ItemCtrl.getTotalCalories(); // Add total calories to UI UICtrl.showTotalCalories(totalCalories); // Remove from UI UICtrl.removeItems(); // Hide UL UICtrl.hideList(); }
بدین صورت برنامه ما کامل شده است. ما می توانیم آموزش را در همین مرحله متوقف کنیم اما من دوست دارم از local storage استفاده کنیم تا با رفرش شدن صفحه، اطلاعات وارد شده پاک نشود. در جلسات بعد به این موضوع می پردازیم.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.