در قسمت قبل پروسه ویرایش آیتم های غذایی را شروع کردیم و با استفاده از event delegation توانستیم مشکل دریافت آیتم ها را از بین ببریم. من در انتهای آن جلسه کد زیر را به شما دادم و از شما خواستم که به نحوه کار آن فکر کنید:
// Update item submit const itemUpdateSubmit = function(e){ if(e.target.classList.contains('edit-item')){ // Get list item id (item-0, item-1) const listId = e.target.parentNode.parentNode.id; // Break into an array const listIdArr = listId.split('-'); // Get the actual id const id = parseInt(listIdArr[1]); // Get item const itemToEdit = ItemCtrl.getItemById(id); // Set current item ItemCtrl.setCurrentItem(itemToEdit); // Add item to form UICtrl.addItemToForm(); } e.preventDefault(); }
آیا به جواب رسیدید؟ e.target ما برابر تگ <i> است که همان تگی دارنده آیکون مداد می باشد. parent یا عنصر پدری آن یک تگ <a> است و پدرِ آن عنصر <a> یک عنصر <li> است. این <li> خصوصیت id را درون خود دارد. به همین دلیل کد را به شکل بالا نوشته ایم تا به <li> برسیم.
پس از دریافت listId آن را از قسمت – جدا کرده ایم. می دانیم که مقادیری شبیه به item-0 و item-1 همان مقدار درون listId است اما ما فقط عدد آن را به عنوان id می خواهم به همین دلیل از split استفاده کرده ام. با استفاده از split مقدارِ درونِ listIdArr یک آرایه با دو عضو خواهد بود. مثلا:
["item", "0"]
بنابراین باید عضوی که index آن برابر با 1 است را دریافت کنیم که همان عدد id می باشد (ایندکس صفر برابر رشته item است). parseInt نیز آن را از رشته به عدد تبدیل می کند. سپس از تابعی به نام getItemById استفاده کرده ایم که هنوز تعریف نشده است اما قرار است بر اساس این id، خود آیتم غذایی را دریافت کرده و به ما بدهد. سپس setCurrentItem آن را گرفته و به currentItem اضافه می کند (currentItem در data structure ما تعریف شده بود و فعلا null است). سپس تابعی به نام addItemToForm خواهیم داشت که آیتم ویرایش شده را به فرم اضافه کند یا به عبارت دیگر آیتم را پس از ویرایش در UI نمایش دهد.
ابتدا باید به کنترلر item ها برویم و getItemById را تعریف کنیم. پایین تر از addItem می نویسیم:
// بقیه کدها // getItemById: function(id){ let found = null; // Loop through items data.items.forEach(function(item){ if(item.id === id){ found = item; } }); return found; }
همانطور که مشاهده می کنید، منطق این کد بسیار ساده است. ما متغیری به نام found تعریف کرده ایم که در ابتدا null است. سپس با یک حلقه forEach بین آیتم های موجود چک می کنیم تا ببینیم آیا این id در بین یکی از این آیتم ها وجود دارد یا خیر؟ اگر وجود داشت، found برابر همان عنصر خواهد بود و در غیر این صورت همان null می باشد. در نهایت found را برمی گردانیم. بالاتر گفتیم که این آیتم به تابعی به نام setCurrentItem پاس داده خواهد شد:
// Get item const itemToEdit = ItemCtrl.getItemById(id); // Set current item ItemCtrl.setCurrentItem(itemToEdit);
بنابراین باید این تابع را نیز تعریف کنیم. من آن را در همان کنترلر item ها و پایین تر از getItemById تعریف می کنیم:
getItemById: function(id){ let found = null; // Loop through items data.items.forEach(function(item){ if(item.id === id){ found = item; } }); return found; }, setCurrentItem: function(item){ data.currentItem = item; },
setCurrentItem نیز بسیار ساده است و فقط آیتم دریافتی را به currentItem درون data structure می دهد. در نهایت باید آیتم ذخیره شده در currentItem را دریافت کرده، ویرایش کرده و در فرم ثبت کنیم. در بالاتر این کد را داشتیم:
// بقیه کدها // // Get item const itemToEdit = ItemCtrl.getItemById(id); // Set current item ItemCtrl.setCurrentItem(itemToEdit); // Add item to form UICtrl.addItemToForm(); // بقیه کدها //
برای تعریف این تابع (addItemToForm) به کنترلر UI بروید و پس از تابع clearInput این کار را انجام بدهید:
// بقیه کدها // clearInput: function(){ document.querySelector(UISelectors.itemNameInput).value = ''; document.querySelector(UISelectors.itemCaloriesInput).value = ''; }, addItemToForm: function(){ document.querySelector(UISelectors.itemNameInput).value = ItemCtrl.getCurrentItem().name; document.querySelector(UISelectors.itemCaloriesInput).value = ItemCtrl.getCurrentItem().calories; UICtrl.showEditState(); } // بقیه کدها //
در این تابع از تابع دیگر به نام getCurrentItem استفاده کرده ایم که آیتم فعلی را به ما می دهد (هنوز آن را تعریف نکرده ایم). این تابع خصوصیتی به نام name را برمی گرداند که همان نام آیتم است که کاربر در هنگام ثبت وارد کرده بود. getCurrentItem خصوصیت دیگری نیز به نام calories برمی گرداند که همان تعداد کالری های وارد شده برای هر آیتم توسط کاربر (هنگام ثبت در اولین بار) است. ما می خواهیم با کلیک روی دکمه ویرایش (آیکون مداد) مقادیر آیتم مورد نظر (نام و کالری هایش) سریعا در فرم قرار بگیرد.
اگر یادتان باشد در جلسات اول کدی نوشتیم که طبق آن تمامی این موارد در هنگام ساخته شدن هر آیتم تعریف می شود:
// Item Controller const ItemCtrl = (function(){ // Item Constructor const Item = function(id, name, calories){ this.id = id; this.name = name; this.calories = calories; } // بقیه کدها //
در نهایت نیز متدی به نام showEditState را صدا زده ایم که قرار است کارش ثبت داده های جدید باشد. هیچ کدام از این دو متد تعریف نشده اند بنابراین باید آن ها را تعریف کنیم. من از getCurrentItem شروع می کنم. به کنترلر item ها بروید و دقیقا زیر setCurrentItem آن را تعریف کنید:
// بقیه کدها // setCurrentItem: function(item){ data.currentItem = item; }, getCurrentItem: function(){ return data.currentItem; } // بقیه کدها //
منطق این کد ساده است چرا که فقط currentItem را برمی گرداند. حالا به کنترلر UI می رویم و پایین تر از clearEditState تابع showEditState را تعریف می کنیم:
// بقیه کدها // showEditState: function(){ document.querySelector(UISelectors.updateBtn).style.display = 'inline'; document.querySelector(UISelectors.deleteBtn).style.display = 'inline'; document.querySelector(UISelectors.backBtn).style.display = 'inline'; document.querySelector(UISelectors.addBtn).style.display = 'none'; }, // بقیه کدها //
با این کار هنگام کلیک روی دکمه ویرایش (آیکون مداد) دکمه های update و delete و back نمایش داده می شوند اما add مخفی می شود. در جلسه بعد باید روی این دکمه ها کار کنیم تا اگر کاربر روی update کلیک کرد، داده های جدید او ثبت شود.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.