برنامه مدیریت کالری غذا: ثبت ویرایش برای آیتم‌ها و کالری کل (2)

Tracalorie Project: Recording Edited Items - Part 2

04 شهریور 1399
برنامه ی مدیریت کالری غذا: ثبت ویرایش برای آیتم ها و کالری کل (2)

در قسمت قبل با استفاده از یک حلقه forEach آیتم غذایی مورد نظرمان را پیدا کرده و آن را به ویرایش می کردیم:

    updateItem: function(name, calories){
      // Calories to number
      calories = parseInt(calories);

      let found = null;

      data.items.forEach(function(item){
        if(item.id === data.currentItem.id){
          item.name = name;
          item.calories = calories;
          found = item;
        }
      });
      return found;
    }

با این کار آیتم ما در data structure به روز رسانی می شود اما در UI تغییری اتفاق نمی افتد چرا که هیچ کدی برای تغییر UI ننوشته ایم. از آنجایی که در کد بالا found را برگردانده ایم می توانیم از آن برای به روز رسانی UI استفاده کنیم. اگر به متد itemUpdateSubmit بروید کد زیر را می بینید:

  // Update item submit
  const itemUpdateSubmit = function(e){
    // Get item input
    const input = UICtrl.getItemInput();

    // Update item
    const updatedItem = ItemCtrl.updateItem(input.name, input.calories);

    e.preventDefault();
  }

بنابراین found درون ثابت updatedItem قرار داده می شود و ما می توانیم با استفاده از همین موضوع و درون همین متد UI را به روز رسانی کنیم. من از متد جدیدی استفاده می کنم که باید آن را تعریف کنیم:

  // Update item submit
  const itemUpdateSubmit = function(e){
    // Get item input
    const input = UICtrl.getItemInput();

    // Update item
    const updatedItem = ItemCtrl.updateItem(input.name, input.calories);

    // Update UI
    UICtrl.updateListItem(updatedItem);

    e.preventDefault();
  }

متد updateListItem قرار است آیتم های غذایی را در UI به روز رسانی کند بنابراین به کنترلر UI رفته و پایین تر از تابع addListItem متد updateListItem را تعریف کنید:

    updateListItem: function(item){
      let listItems = document.querySelectorAll(UISelectors.listItems);

      // Turn Node list into array
      listItems = Array.from(listItems);
    }

در قدم اول با استفاده از querySelector توانسته ایم تمام آیتم های خود را از درون DOM دریافت می کنیم. سپس برای اینکه بتوانیم با استفاده از حلقه ها در بین آیتم ها گردش کنیم باید آن را از یک Node به یک آرایه تبدیل کنیم. به همین دلیل می توانیم از Array.from استفاده کنیم. این متد یک node یا هر چیزی که قابلیت تبدیل شدن به آرایه را داشته باشد گرفته و سپس آن را به آرایه تبدیل می کند.

البته هنوز listItems را به عنوان یک سلکتور تعریف نکرده ایم، بنابراین به قسمت سلکتورها در کنترلر UI می رویم و listItems را تعریف می کنیم:

  const UISelectors = {
    itemList: '#item-list',
    listItems: '#item-list li',
    addBtn: '.add-btn',
    updateBtn: '.update-btn',
    deleteBtn: '.delete-btn',
    backBtn: '.back-btn',
    itemNameInput: '#item-name',
    itemCaloriesInput: '#item-calories',
    totalCalories: '.total-calories'
  }

این هم از listItems. حالا به کد قبلی و تابع updateListItem برمی گردیم تا از حلقه forEach خودمان استفاده کنیم:

    updateListItem: function(item){
      let listItems = document.querySelectorAll(UISelectors.listItems);

      // Turn Node list into array
      listItems = Array.from(listItems);

      listItems.forEach(function(listItem){
        const itemID = listItem.getAttribute('id');

        if(itemID === `item-${item.id}`){
          document.querySelector(`#${itemID}`).innerHTML = `<strong>${item.name}: </strong> <em>${item.calories} Calories</em>
          <a href="#" class="secondary-content">
            <i class="edit-item fa fa-pencil"></i>
          </a>`;
        }
      });
    }

در ابتدا id هر کدام از این آیتم ها را دریافت کرده ایم (با استفاده از getAttribute). سپس با یک شرط if گفته ایم اگر itemID ما برابر با رشته item-X باشد (به صورتی که x عدد آیدی باشد، همان خصوصیت id از item پاس داده شده) می فهمیم که به آیتم غذایی مورد نظر رسیده ایم بنابراین باید آن را به روز رسانی کنیم. کدهای HTML ای که در کد بالا می بینید همان ساختار همیشگی li های ما است و چیز جدیدی ننوشته ایم. دقیقا همین ساختار را در هنگام ثبت آیتم ها نیز داشتیم.

در حال حاضر اگر به مرورگر رفته و این کدها را تست کنیم متوجه می شویم که لیست ما به خوبی به روز رسانی می شود اما پس از ویرایش و به روز رسانی آیتم ها، باز هم در حالت ویرایش باقی می مانیم. یعنی دکمه های Update Meal و غیره سر جای خود هستند و فیلد ها نیز هنوز دارای نوشته می باشند. همچنین مشکل بعدی این است که تعداد کالری کل به روز نمی شود. بنابراین دوباره به itemUpdateSubmit بروید و کدهای زیر را به آن اضافه کنید:

  // Update item submit
  const itemUpdateSubmit = function(e){
    // Get item input
    const input = UICtrl.getItemInput();

    // Update item
    const updatedItem = ItemCtrl.updateItem(input.name, input.calories);

    // Update UI
    UICtrl.updateListItem(updatedItem);

     // Get total calories
     const totalCalories = ItemCtrl.getTotalCalories();
     // Add total calories to UI
     UICtrl.showTotalCalories(totalCalories);

     UICtrl.clearEditState();

    e.preventDefault();
  }

یعنی پس از صدا زدن updateListItem و به روز رسانی آیتم ها، دوباره متد getTotalCalories را صدا زده ایم. باید یادتان باشد که این متد را در جلسات قبل نوشته ایم و کارش محاسبه تعداد کل کالری ها بود. با این حساب تعداد کل کالری ها (آپدیت شده) درون totalCalories قرار می گیرد. سپس showTotalCalories را صدا می زنیم تا مقدار کل کالری را در UI به روز رسانی کند. در نهایت اگر متد clearEditState را صدا بزنیم، از حالت ویرایش خارج می شویم. در ضمن این متد درون خودش متد پاک کردن فیلدها را نیز دارد بنابراین نیازی به پاکسازی جداگانه فیلد ها نداریم.

حالا می توانید به مرورگر خود رفته و کدها را تست کنید. همه چیز باید بدون مشکل برایتان کار کند. در قسمت بعد روی حذف آیتم ها تمرکز خواهیم کرد. یعنی کاربر باید بتواند روی آیکون ضربدر کلیک کرده و آیتم مورد نظرش را حذف کند. همچنین فعلا دکمه back در حالت ویرایش کار نمی کند، یعنی اگر کاربر روی آیکون مداد کلیک کرد و وارد حالت ویرایش شده اما از تصمیم خودش منصرف شد، نمی تواند روی back کلیک کند و بدون ایجاد تغییرات برگردد. در جلسات بعد به این موضوعات می پردازیم.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری پروژه‌های مدرن جاوا اسکریپت توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.