پروژه Drag & Drop: دریافت داده‌های کاربر

Drag & Drop Project: Getting Users Data

15 مرداد 1399
پروژه ی Drag & Drop: دریافت داده های کاربر

در قسمت قبل متدی به نام submitHandler تعریف کرده ایم که باید فرآیند دریافت و ثبت داده های کاربر را مدیریت می کرد اما فعلا فقط مقدار وارد شده در title را log می کند:

  @autobind
  private submitHandler(event: Event) {
    event.preventDefault();
    console.log(this.titleInputElement.value);
  }

هدف اصلی دریافت تمام داده های ورودی (نه فقط Title) و سپس اعتبارسنجی آن ها است تا در نهایت بتوانیم با آن ها کاری انجام دهیم. برای انجام این کار یک متد دیگر تعریف می کنم:

  private gatherUserInput() {

  }

  @autobind
  private submitHandler(event: Event) {
    event.preventDefault();
    const userInput = this.gatherUserInput();
  }

همانطور که می بینید نقشه من این است که متدی به نام gatherUserInput داشته باشیم تا داده های کاربر را دریافت کرده و آن ها را اعتبارسنجی کند. در نهایت نیز این داده ها را return می کند و ما آن را درون متد submitHandler دریافت کرده و به ثابتی به نام userInput می دهیم. برای شروع باید return type را برای متد gatherUserInput تعریف کنیم. ما سه فیلد مشخص در فرم خود داریم: title و description و people بنابراین می توانیم نوع داده آن ها را از نوع Tuple مشخص کنیم. آیا tuple ها را از فصل های اول به یاد دارید؟

    private gatherUserInput(): [string, string, number] {

    }

همانطور که در متد بالا مشخص کرده ایم، این متد یک tuple با سه عضو را برمی گرداند که به ترتیب از نوع رشته، رشته و عدد خواهند بود. در قدم بعدی باید مقادیر وارد شده توسط کاربر را از فیلدهای برنامه بگیریم:

    private gatherUserInput(): [string, string, number] {
        const enteredTitle = this.titleInputElement.value;
        const enteredDescription = this.descriptionInputElement.value;
        const enteredPeople = this.peopleInputElement.value;
    }

در مرحله بعدی باید این ورودی ها را اعتبارسنجی کنیم. البته از آنجایی که پروژه ما یک پروژه تمرینی است، آنچنان اعتبارسنجی سفت و سختی نخواهیم داشت بلکه تنها چک می کنم هیچ کدام از مقادیر وارد شده خالی نباشند. البته در جلسات بعد، اعتبارسنجی را پیچیده تر خواهیم کرد.

  private gatherUserInput(): [string, string, number] {
    const enteredTitle = this.titleInputElement.value;
    const enteredDescription = this.descriptionInputElement.value;
    const enteredPeople = this.peopleInputElement.value;

    if (
      enteredTitle.trim().length === 0 ||
      enteredDescription.trim().length === 0 ||
      enteredPeople.trim().length === 0
    ) {

  }
}

من در یک شرط نوشته ام که آیا طول مقادیر وارد شده برابر صفر است یا خیر؟ خوب به این موضوع فکر کنید. اگر طول یکی از مقادیر وارد شده صفر باشد یعنی کاربر آن را خالی گذاشته است بنابراین نباید این داده ها را قبول کنیم. من در این قسمت یک alert نمایش می دهم:

  private gatherUserInput(): [string, string, number] {
    const enteredTitle = this.titleInputElement.value;
    const enteredDescription = this.descriptionInputElement.value;
    const enteredPeople = this.peopleInputElement.value;

    if (
      enteredTitle.trim().length === 0 ||
      enteredDescription.trim().length === 0 ||
      enteredPeople.trim().length === 0
    ) {
      alert('Invalid input, please try again!');
    } else {
      return [enteredTitle, enteredDescription, +enteredPeople];
    }
  }

من درون این alert پیامی با مضمون «ورودی غیر معتبر، لطفا دوباره سعی کنید» نمایش می دهم تا کاربر بداند مشکلی وجود دارد. از طرفی اگر وارد این شرط نشدیم (هیچ کدام از فیلدها خالی نبود) می توانیم یک tuple را برگردانیم که هر سه فیلد را درون خود داشته باشد. علامت + قبل از enteredPeople برای تبدیل کردن ورودی به عدد است. در حالت عادی دریافت تمام ورودی های کاربر در جاوا اسکریپت به صورت رشته ای است اما enteredPeople قرار است تعداد افرادی باشد که روی پروژه کار می کنند بنابراین نیاز به عدد داریم. اگر شما این علامت مثبت را نگذارید تایپ اسکریپت به شما خطا خواهد داد. چرا؟ به دلیل اینکه در قسمت return type مشخص کرده بودیم عضو سوم tuple ما از نوع عدد خواهد بود:

  private gatherUserInput(): [string, string, number] {
// بقیه کدها //

البته روش های دیگری به جای استفاده از علامت مثبت وجود دارد. به طور مثال:

return [enteredTitle, enteredDescription, parseFloat(enteredPeople)];

انتخاب با خودتان است اما از آنجایی که علامت مثبت کوتاه تر و ساده تر است من همان را انتخاب می کنم. در حال حاضر تایپ اسکریپت به ما خطا می دهد. آیا می توانید خودتان بفهمید مشکل از کجاست؟ ما در قسمت return type مشخص کرده ایم که این متد همیشه یک tuple برمی گرداند اما اگر وارد شرط if شویم چیزی را برنمی گردانیم بلکه فقط یک Alert را نمایش می دهیم! این منشا خطا است. چند روش برای حل این مشکل وجود دارد. مثلا می توانیم یک خطای جدید را throw کنیم. از آنجایی که من نمی خواهم کدهای مدیریت خطا را نیز بنویسم فعلا از این روش استفاده نمی کنم. راه حل دیگر این است که هیچ چیز خاصی را return نکنیم و من همین راه حل را ترجیح می دهم:

// بقیه کدها //
    if (
      enteredTitle.trim().length === 0 ||
      enteredDescription.trim().length === 0 ||
      enteredPeople.trim().length === 0
    ) {
      alert('Invalid input, please try again!');
      return;
    } else {
      return [enteredTitle, enteredDescription, +enteredPeople];
    }
  }

طبیعتا باز هم با خطا روبرو می شویم چرا که «هیچ چیز» برابر با یک tuple نیست! بنابراین در قسمت تعیین return type باید void را نیز اضافه کنیم:

  private gatherUserInput(): [string, string, number] | void {
    const enteredTitle = this.titleInputElement.value;
    const enteredDescription = this.descriptionInputElement.value;
    const enteredPeople = this.peopleInputElement.value;

    if (
      enteredTitle.trim().length === 0 ||
      enteredDescription.trim().length === 0 ||
      enteredPeople.trim().length === 0
    ) {
      alert('Invalid input, please try again!');
      return;
    } else {
      return [enteredTitle, enteredDescription, +enteredPeople];
    }
  }

با این حساب به تایپ اسکریپت گفته ایم که متد ما یا یک tuple برمی گرداند یا void (هیچ چیزی برنمی گرداند) که یک union type محسوب می شود.

نکته: اگر یادتان باشد return کردن هیچ چیز در اصل undefined است بنابراین باید آن را قرار بدهیم اما در متدها همیشه به جای undefined از void استفاده می کنیم (هر دو یکی هستند). اگر این مسئله را یادتان نمی آید به قسمت های ابتدایی این دوره مراجعه کنید.

حالا باید به متد submitHandler برگردیم:

   @autobind
  private submitHandler(event: Event) {
    event.preventDefault();
    const userInput = this.gatherUserInput();
  }

ما داده های کاربر را درون userInput خواهیم داشت که یا یک tuple است یا void و undefined. برای چک کردن این مورد مشکلی وجود دارد. تایپ اسکریپت در نهایت به جاوا اسکریپت تبدیل می شود و tuple ها در جاوا اسکریپت وجود ندارند بنابراین نمی توانیم با یک شرط if بگوییم اگر userInput از نوع tuple بود فلان کار را انجام بده. راه حل این مشکل ساده این است که به یاد داشته باشیم tuple ها در نهایت نوعی آرایه خاص هستند (تعداد اعضایشان ثابت است) و زمانی که کدهایمان به جاوا اسکریپت کامپایل شود، tuple ها همگی به آرایه های عادی تبدیل می شوند. بنابراین:

  @autobind
  private submitHandler(event: Event) {
    event.preventDefault();
    const userInput = this.gatherUserInput();
    if (Array.isArray(userInput)) {
      const [title, desc, people] = userInput;
      console.log(title, desc, people);
    }
  }

یعنی اگر userInput یک آرایه بود از array destructuring استفاده می کنیم و تک تک مقادیر آن را به صورت متغیرهای جداگانه از آرایه خارج کرده و سپس log می کنیم.

log کردن داده های کاربر از userInput
log کردن داده های کاربر از userInput

در حال حاضر کدهایمان هیچ خطایی ندارند اما برای بهتر شدن UI و UX برنامه خوب است که پس از ثبت داده ها توس کاربر، فیلدها را خالی کنیم بنابراین:

  private clearInputs() {
    this.titleInputElement.value = '';
    this.descriptionInputElement.value = '';
    this.peopleInputElement.value = '';
  }

  @autobind
  private submitHandler(event: Event) {
    event.preventDefault();
    const userInput = this.gatherUserInput();
    if (Array.isArray(userInput)) {
      const [title, desc, people] = userInput;
      console.log(title, desc, people);
      this.clearInputs();
    }
  }

حالا پس از اینکه کاربر داده هایش را ارسال کرد، متد clearInputs صدا زده شده و تمام فیلدها خالی می شوند تا ظاهر برنامه جذاب تر شود.

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

دیدگاه‌های شما (1 دیدگاه)

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

آرش بیات
18 مرداد 1399
ممنون از سایت روکسو :)

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

ما را دنبال کنید
اینستاگرام روکسو تلگرام روکسو ایمیل و خبرنامه روکسو