FormControl و Input غير متوافقين؟ حل مشكلة Angular Material

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: الألم المألوف لكل مطور Angular

\n\n

هل سبق لك أن أمضيت ساعة في البحث عن خطأ كان مختبئًا حرفيًا في سطر واحد من الكود؟ إذا كنت تعمل مع Angular Material Autocomplete وواجهت رسالة Can't bind to 'formControl' since it isn't a known property of 'input' — فأنت لست وحدك. هذا السؤال على Stack Overflow حصد آلاف المشاهدات، وليس من دون سبب. يظهر الخطأ في أكثر اللحظات غير المتوقعة، عندما يبدو أن كل شيء يعمل بشكل مثالي.

\n\n

في هذه المقالة، سنستعرض أسباب ظهور الخطأ، ونقارن بالتفصيل بين ثلاث طرق لإصلاحه، ونعرض أمثلة عملية بلغة TypeScript. بعد القراءة، لن تتمكن فقط من إصلاح الإكمال التلقائي، بل ستفهم أيضًا بنية Angular بشكل أعمق. هيا بنا!

\n\n

لماذا يظهر خطأ Can't bind to 'formControl'؟

\n\n

دعنا نصل إلى صلب الموضوع مباشرة. يظهر الخطأ عندما يحاول Angular ربط التوجيه formControl بعنصر <input>، لكنه لا يجده في الوحدة الحالية. يبدو هذا منطقيًا، لكن الشيطان يكمن في التفاصيل.

\n\n

في الواقع، formControl هو محدد (selector) لتوجيه (directive) يعد جزءًا من وحدة ReactiveFormsModule. إذا نسيت استيراد هذه الوحدة أو قمت باستيرادها بشكل خاطئ، فإن Angular ببساطة لا يعرف ماذا يفعل بالخاصية [formControl] الموجودة على حقل الإدخال الخاص بك.

\n\n

إليك موقفًا نموذجيًا: تقوم بإنشاء مكون جديد مع إكمال تلقائي، وتضيف FormControl في كود TypeScript، وفي القالب تكتب:

\n\n
<input type="text" [formControl]="myControl" [matAutocomplete]="auto">\n<mat-autocomplete #auto="matAutocomplete">\n  <mat-option *ngFor="let option of filteredOptions | async" [value]="option">\n    {{option}}\n  </mat-option>\n</mat-autocomplete>
\n\n

وفجأة — بام! يظهر خطأ أحمر في وحدة التحكم. هل هذا مألوف؟ إذن تابع القراءة.

\n\n

الطريقة 1: استيراد ReactiveFormsModule (الأسهل والأصح)

\n\n

الطريقة الأولى والأكثر وضوحًا هي التأكد من استيراد ReactiveFormsModule في الوحدة المناسبة. بالنسبة للمكونات المستقلة (standalone) (Angular 14+) أو الوحدات التقليدية، تختلف الإجراءات قليلاً.

\n\n

للوحدات التقليدية (NgModule)

\n\n

افتح ملف الوحدة الذي تم تسجيل مكونك فيه (مثل app.module.ts أو shared.module.ts)، وأضف الاستيراد:

\n\n
import { ReactiveFormsModule } from '@angular/forms';\nimport { MatAutocompleteModule } from '@angular/material/autocomplete';\nimport { MatInputModule } from '@angular/material/input';\n\n@NgModule({\n  imports: [\n    ReactiveFormsModule,\n    MatAutocompleteModule,\n    MatInputModule,\n    // استيرادات أخرى\n  ],\n  // ...\n})\nexport class AppModule { }
\n\n

هام: بدون MatInputModule، لن يعمل التوجيه matInput أيضًا، وستحصل على خطأ مشابه. قم باستيراد الوحدات الثلاث معًا.

\n\n

للمكونات المستقلة (Angular 14+ و Angular 17)

\n\n

إذا كنت تستخدم البنية الجديدة، يتم الاستيراد مباشرة في المكون:

\n\n
import { Component } from '@angular/core';\nimport { ReactiveFormsModule, FormControl } from '@angular/forms';\nimport { MatAutocompleteModule } from '@angular/material/autocomplete';\nimport { MatInputModule } from '@angular/material/input';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n  selector: 'app-search',\n  standalone: true,\n  imports: [\n    ReactiveFormsModule,\n    MatAutocompleteModule,\n    MatInputModule,\n    AsyncPipe\n  ],\n  template: `\n    <input type="text" [formControl]="myControl" [matAutocomplete]="auto">\n    <mat-autocomplete #auto="matAutocomplete">\n      <mat-option *ngFor="let option of filteredOptions | async" [value]="option">\n        {{option}}\n      </mat-option>\n    </mat-                

المدونات

توصيات الكتب