تطوير تطبيقات الويب باستخدام Angular


الدرس: استمع إلى المستخدم باستخدام -Forms طريقة القالب


الصفحة السابقة
حتى الآن ، في هذه الدورة ، تعلمت كيفية إنشاء تطبيق ديناميكي يسمح بتبادل المعلومات بين المكونات باستخدام الخدمات والملاحظات(observables) ، مما يغير العرض وفقًا للتوجيه ويتفاعل مع أحداث معينة قادمة من المستخدم ، مثل النقر على زر ، على سبيل المثال. ومع ذلك ، في الوقت الحالي ، تم ترميز جميع البيانات التي استخدمتها في التطبيق ، وهذا يعني أنه لم يتم توفيرها من قبل المستخدم ولا من قبل خادم. في الفصول التالية ، ستتعلم كيفية التفاعل مع المستخدم ومع الخوادم من أجل إنشاء تطبيق ديناميكي بالكامل.

في Angular، هناك طريقتان رئيسيتان لإنشاء النماذج:

  • طريقة القالب : تقوم بإنشاء النموذج الخاص بك في القالب ، وتقوم Angular بتحليله لفهم المدخلات المختلفة وإتاحة المحتوى ؛
  • الطريقة التفاعلية : تقوم بإنشاء النموذج الخاص بك في TypeScript وفي القالب ، ثم تقوم بربطه يدويًا - هذا النهج أكثر تعقيدًا ، ولكنه يسمح بمزيد من التحكم ونهج ديناميكي.
لا تنس استيراد نماذج FormModule إلى AppModule إذا لم تكن قد قمت بذلك بالفعل!

في بقية هذا الفصل سوف نكتشف طريقة القالب.

قم بإنشاء النموذج


لفهم هذه الطريقة وممارستها ، ستنشئ مكونًا جديدًا   EditAppareilComponent  سيسمح للمستخدم بتسجيل جهاز كهربائي جديد:

<div class="row">
  <div class="col-sm-8 col-sm-offset-2">
    <form>
      <div class="form-group">
        <label for="name">
          Nom de l'appareil
        </label>
        <input type="text" id="name" class="form-control">
      </div>
      <div class="form-group">
        <label for="status">
          État de l'appareil
        </label>
        <select id="status" class="form-control">
          <option value="allumé">Allumé</option>
          <option value="éteint">Éteint</option>
        </select>
      </div>
      <button class="btn btn-primary">Enregistrer</button>
    </form>
  </div>
</div>
يقوم Angular بتصفح القالب الخاص بك والعثور على العلامة   <form> ، وإنشاء كائن يمكن استخدامه من كود TypeScript الخاص بك. قبل الشروع في تقديم النموذج ، يجب عليك تنبيه Angular بالإدخالات التي ستتوافق معها   controls ، أي الحقول التي سيتم تقديم محتواها. للقيام بذلك ، ما عليك سوى إضافة سمتين إلى المدخلات المعنية: سمة name ، والتي تتوافق مع مفتاح زوجي قيمة-مفتاح الذي سيتم إرجاعه ، والسمة   ngModel ، بدون أقواس أو أقواس. تشير هذه السمة الثانية إلى Angular أنك تريد حفظ عنصر التحكم هذا:

<div class="form-group">
    <label for="name">
      Nom de l'appareil
    </label>
    <input type="text" id="name" class="form-control" name="name" ngModel>
</div>
<div class="form-group">
    <label for="status">
      État de l'appareil
    </label>
    <select id="status" class="form-control" name="status" ngModel>
      <option value="allumé">Allumé</option>
      <option value="éteint">Éteint</option>
    </select>
</div>
يجب علينا الآن إعداد إدارة تقديم هذا النموذج. في نموذجك ، بدلاً من إضافة حدث إلى الزر ، ستعلن عن زر النوع submit ، وتضيف الرمز التالي في العلامة <form> :


<form (ngSubmit)="onSubmit(f)" #f="ngForm">
<button class="btn btn-primary" type="submit">Enregistrer</button>
يؤدي الإعلان عن زر الإرسال submit داخل
إلى تنشيط سلوك إرسال HTML الكلاسيكي. بإضافة السمة   (ngSubmit) ، تتلقى هذا الإرسال وتنفذ الطريقة   onSubmit()  (التي لم تقم بإنشائها بعد) .
 تسمى السمة  #f مرجع محلي. ما عليك سوى إعطاء اسم للكائن الذي تضيف إليه هذه السمة ؛ سيتم استخدام هذا الاسم بعد ذلك بواسطة Angular . هذا هو الحال أيضًا هنا: يتم استدعاء النموذج   f  ثم يتم تمريره كوسيطة لطريقة التقديم.
بشكل عام ، نحن لا نعطي قيمة لمرجع محلي: نحن ببساطة نكتب   #f  أو   #my-name  . في هذه الحالة المحددة لنموذج في طريقة القالب ، نقوم بتعيين القيمة   ngForm  للوصول إلى الكائن الذي تم إنشاؤه بواسطة Angular .
التلخيص: عندما ينقر المستخدم على زر  الإرسال   ، يتم تنفيذ الطريقة التي وقع تعيينها في  (ngSubmit) ، وبفضل المرجع المحلي   #f="ngForm"، يمكنك تمرير الكائن إلى الطريقة (وبالتالي استرداده في كود TypeScript ) .
الآن قم بإنشاء طريقة   onSubmit()  لتلقي المعلومات من النموذج. في الوقت الحالي ، سوف تعرضها ببساطة في وحدة التحكم:

onSubmit(form: NgForm) {
    console.log(form.value);
}
هنا يمكنك استخدام الخاصية   value  لـ   NgForm  . يحتوي الكائن   NgForm  (للاستيراد منه   @angular/forms  ) على العديد من الخصائص المثيرة للاهتمام ؛ سأشرح فقط بعضها في هذه الدورة ، ولكن يمكنك العثور على القائمة الكاملة في الوثائق الرسمية.
للوصول إلى النموذج، إنشاء طريق جديد في   AppModule  و   routerLink  في شريط القوائم:


    const appRoutes: Routes = [
      { path: 'appareils', canActivate: [AuthGuard], component: AppareilViewComponent },
      { path: 'appareils/:id', canActivate: [AuthGuard], component: SingleAppareilComponent },
      { path: 'edit', canActivate: [AuthGuard], component: EditAppareilComponent },
      { path: 'auth', component: AuthComponent },
      { path: '', component: AppareilViewComponent },
      { path: 'not-found', component: FourOhFourComponent },
      { path: '**', redirectTo: 'not-found' }
    ];
    <ul class="nav navbar-nav">
        <li routerLinkActive="active"><a routerLink="auth">Authentification</a></li>
        <li routerLinkActive="active"><a routerLink="appareils">Appareils</a></li>
        <li routerLinkActive="active"><a routerLink="edit">Nouvel appareil</a></li>
    </ul>
    
انتقل إلى هذه الصفحة الجديدة. إذا قمت بكتابة "Television" كاسم واخترت "Off" ثم انقر فوق "Save" ، في وحدة التحكم لديك:
Angular web site
هذا كل شيء ، يمكنك الوصول إلى معلومات النموذج! قبل معالجتها وإنشاء جهاز جديد ، ستضيف أولاً التحقق من صحة النموذج ، بحيث لا يمكن للمستخدم إرساله دون إدخال بيانات صالحة.

التحقق من صحة البيانات


بالنسبة لشكل هذا التطبيق ، يمكننا القول أن اسم الجهاز هو حقل إلزامي. لإضافة هذا الالتزام ، ما عليك سوى إضافة التوجيه التالي:

<input type="text" id="name" class="form-control" name="name" ngModel required>
تبدو هذه السمة مثل سمة HTML5 القياسية ، ولكن لاحظ أن Angular يُعطّل تلقائيا سلوك التحقق من الصحة HTML5 .

الحقل إلزامي ، ولكن لا يزال من الممكن إرسال النموذج لأنك لم تدمج بعد حالة التحقق من صحة النموذج. لتحقيق ذلك ، ستقوم بربط   disabled  خاصية الزر بخاصية   invalid  النموذج ، والتي يتم توفيرها بواسطة Angular :

<button class="btn btn-primary" type="submit" [disabled]="f.invalid">Enregistrer</button>
يمكنك استخدام المرجع المحلي   f  للوصول إلى الكائن   NgForm ، وبالتالي خصائصه   invalid ، وتعطيل الزر إذا عاد   true  .

سيكون من المثير للاهتمام إعلان إيقاف تشغيل الجهاز افتراضيًا حتى لا تترك هذا الحقل فارغًا. لإعلان استجابة افتراضية ، ستقوم بإنشاء متغير TypeScript وربطه بخاصية   ngModel  التحكم:

export class EditAppareilComponent implements OnInit {

  defaultOnOff = 'éteint';

  constructor() { }
<select id="status" class="form-control" name="status" [ngModel]="defaultOnOff">
      <option value="allumé">Allumé</option>
      <option value="éteint">Éteint</option>
</select>
وبالتالي ، لا يمكن إرسال النموذج إلا إذا لم يكن حقل "اسم الجهاز" فارغًا ، ويمنع الخيار الذي تم اختياره بشكل افتراضي أن يكون الحقل الثاني فارغًا أيضًا.

يبقى فقط لاستغلال هذه البيانات وإنشاء جهاز جديد!

استخدم البيانات


في الطريقة   onSubmit() ، سوف تقوم باسترداد البيانات وتعيينها إلى ثابتين لإرسالها إلى   AppareilService  :

onSubmit(form: NgForm) {
    const name = form.value['name'];
    const status = form.value['status'];
}
نظرًا لأنك تعلم أن النموذج سيحتوي بالضرورة على حقل   name  وحقل   status  ، فأنت تعلم أنه يمكنك استخدام هذه البنية دون مشكلة.

الآن قم بإنشاء الطريقة   AppareilService  التي سيتم من خلالها إنشاء الجهاز الجديد:

addAppareil(name: string, status: string) {
    const appareilObject = {
      id: 0,
      name: '',
      status: ''
    };
    appareilObject.name = name;
    appareilObject.status = status;
    appareilObject.id = this.appareils[(this.appareils.length - 1)].id + 1;
    this.appareils.push(appareilObject);
    this.emitAppareilSubject();
}
تقوم هذه الطريقة بإنشاء كائن بالتنسيق الصحيح ، وتعيين الاسم والحالة التي تم تمريرها إليه كوسيطة. يأخذ سطر المعرف معرف آخر عنصر حالي للصفيف ويضيف 1. ثم ، تتم إضافة الكائن المكتمل إلى الصفيف ويتم تشغيل الموضوع لإبقاء كل شيء محدثًا.

يبقى فقط لدمج هذه الوظيفة في   EditAppareilComponent  . سيكون من المثير للاهتمام أنه بمجرد إنشاء الجهاز ، تتم إعادة توجيه المستخدم إلى قائمة الأجهزة. لا تنس استيراد الموجه وحقنه لهذا ، بالإضافة إلى   AppareilService  :

export class EditAppareilComponent implements OnInit {

  defaultOnOff = 'éteint';

  constructor(private appareilService: AppareilService,
              private router: Router) { }

  ngOnInit() {
  }

  onSubmit(form: NgForm) {
    const name = form.value['name'];
    const status = form.value['status'];
    this.appareilService.addAppareil(name, status);
    this.router.navigate(['/appareils']);
  }

}
ها أنت ذا! الآن ، بفضل نموذج بسيط يُدار بواسطة طريقة القالب ، يمكن للمستخدم إنشاء جهاز جديد للقائمة.