97- آموزش جاوااسکریپت | پروژه عملی: قسمت 10 از 12- پیادهسازی Back، Delete و Clear All در اپلیکیشن مدیریت کالری
در این بخش، عملکرد دکمه Back برای خروج از حالت ویرایش، حذف یک آیتم از داده و رابط کاربری، و پاککردن همه آیتمها همراه با بهروزرسانی مجموع کالریها پیادهسازی میشود.
در این بخش، سه قابلیت مهم به اپلیکیشن مدیریت کالری اضافه میشود:
- دکمه
Backبرای خروج از حالت ویرایش - دکمه
Deleteبرای حذف آیتم انتخابشده - دکمه
Clear Allبرای حذف همه آیتمها
هدف این است که علاوه بر حذف دادهها از ساختار اصلی برنامه، رابط کاربری نیز همزمان بهروزرسانی شود و مجموع کالریها مقدار درست را نشان دهد.
پیادهسازی دکمه Back
برای دکمه Back نیاز به منطق پیچیدهای نداریم. چون از قبل در UIController متدی به نام clearEditState داریم، کافی است با کلیک روی این دکمه همان متد را اجرا کنیم.
ثبت رویداد دکمه Back
document
.querySelector(UISelectors.backBtn)
.addEventListener('click', UIController.clearEditState);
نتیجه
با کلیک روی دکمه Back:
- فیلدهای فرم پاک میشوند
- دکمههای مربوط به ویرایش مخفی میشوند
- دکمه
Addدوباره نمایش داده میشود
پیادهسازی حذف یک آیتم
در مرحله بعد، قابلیت حذف آیتم انتخابشده را اضافه میکنیم. این حذف باید در سه بخش انجام شود:
- حذف از ساختار داده
- حذف از رابط کاربری
- بهروزرسانی مجموع کالریها
ثبت رویداد دکمه Delete
ابتدا باید برای دکمه حذف، یک event listener ثبت کنیم.
document
.querySelector(UISelectors.deleteBtn)
.addEventListener('click', itemDeleteSubmit);
ساخت تابع itemDeleteSubmit
این تابع عملیات اصلی حذف را انجام میدهد. ابتدا آیتم جاری دریافت میشود، سپس از ساختار داده حذف میشود، بعد از رابط کاربری پاک میشود و در نهایت مجموع کالریها و وضعیت فرم بهروزرسانی میشوند.
const itemDeleteSubmit = function (e) {
e.preventDefault();
const currentItem = ItemController.getCurrentItem();
ItemController.deleteItem(currentItem.id);
UIController.deleteListItem(currentItem.id);
const totalCalories = ItemController.getTotalCalories();
UIController.showTotalCalories(totalCalories);
UIController.clearEditState();
};
حذف آیتم از ساختار داده
برای حذف آیتم از آرایه items، ابتدا لیست شناسهها را با map میگیریم، سپس اندیس آیتم موردنظر را پیدا کرده و با splice آن را حذف میکنیم.
متد deleteItem در ItemController
deleteItem: function (id) {
const ids = data.items.map(function (item) {
return item.id;
});
const index = ids.indexOf(id);
if (index !== -1) {
data.items.splice(index, 1);
}
}
توضیح
در این روش:
- با
mapفقط شناسهها استخراج میشوند - با
indexOfمحل آیتم مشخص میشود - با
spliceهمان آیتم از آرایه حذف میشود
حذف آیتم از رابط کاربری
بعد از حذف آیتم از دادهها، باید همان آیتم از لیست HTML نیز حذف شود.
متد deleteListItem در UIController
deleteListItem: function (id) {
const itemID = `#item-${id}`;
const item = document.querySelector(itemID);
if (item) {
item.remove();
}
}
توضیح
در این متد:
- شناسه DOM آیتم با الگوی
item-{id}ساخته میشود - عنصر موردنظر از صفحه انتخاب میشود
- در صورت وجود، از DOM حذف میشود
بهروزرسانی مجموع کالریها بعد از حذف
بعد از حذف یک آیتم، مقدار مجموع کالریها باید دوباره محاسبه و در رابط کاربری نمایش داده شود.
const totalCalories = ItemController.getTotalCalories();
UIController.showTotalCalories(totalCalories);
خروج از حالت ویرایش بعد از حذف
پس از حذف آیتم، بهتر است فرم از حالت ویرایش خارج شود تا کاربر دوباره بتواند آیتم جدید اضافه کند.
UIController.clearEditState();
پیادهسازی دکمه Clear All
در این بخش میخواهیم با کلیک روی دکمه Clear All، همه آیتمها از دادهها و رابط کاربری حذف شوند.
افزودن selector دکمه Clear All
ابتدا باید selector مربوط به این دکمه را در UISelectors اضافه کنیم.
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'
};
ثبت رویداد دکمه Clear All
حالا event listener مربوط به پاککردن همه آیتمها را ثبت میکنیم.
document
.querySelector(UISelectors.clearBtn)
.addEventListener('click', clearAllItemsClick);
ساخت تابع clearAllItemsClick
این تابع همه آیتمها را از دادهها حذف میکند، آیتمهای موجود در رابط کاربری را پاک میکند، مجموع کالریها را بهروزرسانی میکند و در صورت نیاز لیست را مخفی میسازد.
const clearAllItemsClick = function () {
ItemController.clearAllItems();
UIController.removeItems();
const totalCalories = ItemController.getTotalCalories();
UIController.showTotalCalories(totalCalories);
UIController.hideList();
};
حذف همه آیتمها از ساختار داده
در ItemController، حذف همه آیتمها بسیار ساده است. کافی است آرایه items را خالی کنیم.
clearAllItems: function () {
data.items = [];
}
حذف همه آیتمها از رابط کاربری
در UIController، ابتدا همه آیتمهای لیست گرفته میشوند، سپس NodeList به آرایه تبدیل میشود و در نهایت هر آیتم از DOM حذف میگردد.
removeItems: function () {
let listItems = document.querySelectorAll(UISelectors.listItems);
listItems = Array.from(listItems);
listItems.forEach(function (item) {
item.remove();
});
}
مخفیکردن لیست بعد از پاکسازی کامل
اگر همه آیتمها حذف شوند، بهتر است خود لیست نیز مخفی شود تا خط یا فضای خالی در صفحه باقی نماند.
UIController.hideList();
نمونهای از متد hideList:
hideList: function () {
document.querySelector(UISelectors.itemList).style.display = 'none';
}
نسخه نهایی رویدادها در App Controller
در نهایت، بخش event listenerها به شکل زیر کاملتر میشود:
const loadEventListeners = function () {
document
.querySelector(UISelectors.backBtn)
.addEventListener('click', UIController.clearEditState);
document
.querySelector(UISelectors.deleteBtn)
.addEventListener('click', itemDeleteSubmit);
document
.querySelector(UISelectors.clearBtn)
.addEventListener('click', clearAllItemsClick);
};
نسخه نهایی توابع این بخش
const itemDeleteSubmit = function (e) {
e.preventDefault();
const currentItem = ItemController.getCurrentItem();
ItemController.deleteItem(currentItem.id);
UIController.deleteListItem(currentItem.id);
const totalCalories = ItemController.getTotalCalories();
UIController.showTotalCalories(totalCalories);
UIController.clearEditState();
};
const clearAllItemsClick = function () {
ItemController.clearAllItems();
UIController.removeItems();
const totalCalories = ItemController.getTotalCalories();
UIController.showTotalCalories(totalCalories);
UIController.hideList();
};
کد نهایی این بخش
const ItemController = (function () {
const data = {
items: [],
currentItem: null,
totalCalories: 0
};
return {
getCurrentItem: function () {
return data.currentItem;
},
deleteItem: function (id) {
const ids = data.items.map(function (item) {
return item.id;
});
const index = ids.indexOf(id);
if (index !== -1) {
data.items.splice(index, 1);
}
},
clearAllItems: function () {
data.items = [];
},
getTotalCalories: function () {
let total = 0;
data.items.forEach(function (item) {
total += item.calories;
});
data.totalCalories = total;
return data.totalCalories;
}
};
})();
const UIController = (function () {
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'
};
return {
showTotalCalories: function (totalCalories) {
document.querySelector(UISelectors.totalCalories).textContent = totalCalories;
},
clearEditState: function () {
document.querySelector(UISelectors.itemNameInput).value = '';
document.querySelector(UISelectors.itemCaloriesInput).value = '';
document.querySelector(UISelectors.updateBtn).style.display = 'none';
document.querySelector(UISelectors.deleteBtn).style.display = 'none';
document.querySelector(UISelectors.backBtn).style.display = 'none';
document.querySelector(UISelectors.addBtn).style.display = 'inline';
},
deleteListItem: function (id) {
const itemID = `#item-${id}`;
const item = document.querySelector(itemID);
if (item) {
item.remove();
}
},
removeItems: function () {
let listItems = document.querySelectorAll(UISelectors.listItems);
listItems = Array.from(listItems);
listItems.forEach(function (item) {
item.remove();
});
},
hideList: function () {
document.querySelector(UISelectors.itemList).style.display = 'none';
},
getSelectors: function () {
return UISelectors;
}
};
})();
const App = (function (ItemController, UIController) {
const UISelectors = UIController.getSelectors();
const loadEventListeners = function () {
document
.querySelector(UISelectors.backBtn)
.addEventListener('click', UIController.clearEditState);
document
.querySelector(UISelectors.deleteBtn)
.addEventListener('click', itemDeleteSubmit);
document
.querySelector(UISelectors.clearBtn)
.addEventListener('click', clearAllItemsClick);
};
const itemDeleteSubmit = function (e) {
e.preventDefault();
const currentItem = ItemController.getCurrentItem();
ItemController.deleteItem(currentItem.id);
UIController.deleteListItem(currentItem.id);
const totalCalories = ItemController.getTotalCalories();
UIController.showTotalCalories(totalCalories);
UIController.clearEditState();
};
const clearAllItemsClick = function () {
ItemController.clearAllItems();
UIController.removeItems();
const totalCalories = ItemController.getTotalCalories();
UIController.showTotalCalories(totalCalories);
UIController.hideList();
};
return {
init: function () {
loadEventListeners();
}
};
})(ItemController, UIController);
App.init();
جمعبندی
در این بخش، مدیریت حذف در اپلیکیشن کاملتر شد. اکنون کاربر میتواند:
- با دکمه
Backاز حالت ویرایش خارج شود - یک آیتم مشخص را حذف کند
- همه آیتمها را یکجا پاک کند
- مجموع کالریها را بعد از هر تغییر بهصورت درست ببیند
در بخش بعدی، میتوان دادهها را در localStorage ذخیره کرد تا با رفرش صفحه اطلاعات از بین نروند.