حزمة التحقق الجديدة من أجل React on Mobx @ quantumart / mobx-form-validation kit

مساء الخير
أريد أن أتحدث اليوم عن حزمة جديدة لعمليات التحقق غير المتزامنة في المشروعات التي تستند إلى React و Mobx والمكتوبة في Typescript .
يتضمن تطوير Modern Frontend قدرًا كبيرًا من المنطق عند ملء الصفحات بالوثائق والاستبيانات والمستندات الخاصة بالقرض وأوامر الدفع وصفحات التسجيل على الموقع. يقع العبء المنطقي الرئيسي على عمليات التحقق من الصحة. فكر المطورين الزاويون في هذه النقطة وقدموا للمطورين لهذه الأغراض استخدام آلية FormControl المضمنة ، والتي ، على الرغم من أنها تحتوي على عدد من العيوب ، إلا أنها لا تزال أفضل من الغياب الكامل لمثل هذا الحل على React . الموقف معقد بسبب حقيقة أن الاتجاه الحالي لتطوير React ينطوي على استخدام mobx لتنظيم منطق العمل.
في مواجهة هذه المشكلات ، حلناها جميعًا عن طريق كتابة حزمة: @ quantumart / mobx-form-validation-kit

مزايا الحزمة:
  • تماما على TypeScript
  • متوافق مع Mobx (الإصدار 4 ، الذي يدعم ، المفضل لدى الجميع ، IE10)
  • مصممة للعمل في React (يمكن استخدامها في المشاريع دون رد فعل)
  • مصممة للتحقق من صحة غير متزامن
  • سهل التضمين في مشروع قائم.

تعليمات للعمل مع الحزمة تحت خفض.


في البداية ، سنصف وظيفة حزمة @ quantumart / mobx-valid-kit-validation ، في نهاية المقال سنكتب صفحة تعمل بشكل كامل مع مثال على نموذج التسجيل على الموقع.

FormControl


تتيح لك @ quantumart / mobx-form-validation-kit إنشاء طبقة بين البيانات المصدر والنموذج لعرضه. والذي ، بدوره ، يسمح لك بالتحقق من صحتها ، وإذا لزم الأمر ، قم بتغيير البيانات قبل الوصول إلى الكائن الأصلي.

تحتوي مكتبة @ quantumart / mobx-form-validation-kit على ثلاث فئات رئيسية (مكونات التحقق من الصحة) لإدارة النموذج:
  • FormGroup - يسمح لك بدمج مكونات التحقق من الصحة معًا. تتم كتابة الفصل ، ويسمح لك بإعادة تشكيل الواجهة بقائمة الحقول كمعلمة عامة. يتم تسجيل أي بشكل افتراضي ، فمن المستحسن بشدة عدم استخدامه دون كتابة ، ولكن هناك احتمال.
  • FormControl - يستخدم للتحقق من صحة حقل معين ، الفئة الأكثر استخدامًا. تتم كتابة الفصل ، ويأخذ كمعلمة عامة نوع المتغير الذي يجب تخزينه. بشكل افتراضي ، يتم تسجيل السلسلة ، لأن الافتراضي هو سلسلة ، كخيار الأكثر خاصة للنماذج.
  • FormArray - يسمح لك بإنشاء وإدارة مجموعة من مكونات التحقق من الصحة.

بالإضافة إلى ذلك ، هناك فصول تجريدية أساسية
  • AbstractControl - الفئة الأساسية لكافة فئات التحقق من الصحة المدرجة ، وليس كتابتها.
  • FormAbstractControl - الفئة الأساسية لـ FormGroup و FormArray ، غير مكتوبة.
  • FormAbstractGroup - ليست فئة أساسية مكتوبة لـ FormControl ، تحتوي على ارتباط إلى عنصر html الذي يتم تقديمه.

ستكون أفضل ممارسة لإنشاء نموذج التحقق من صحة الفكرة التالية.
يتم إنشاء كائن من النوع FormGroup واحد على النموذج ويتم بالفعل سرد الحقول فيه
this.form = new FormGroup<IUserInfo>({ name: new FormControl( this.userInfo.name, [], v => (this.userInfo.name = v) ), surname: new FormControl( this.userInfo.surname, [], v => (this.userInfo.surname = v) ) // … }); 

يدعم FormGroup التعشيش ، أي
 this.form = new FormGroup<IUserInfo>({ name: new FormControl( this.userInfo.name, [], v => (this.userInfo.name = v) ), surname: new FormControl( this.userInfo.surname, [], v => (this.userInfo.surname = v) ) passport: new FormGroup<IPassport >({ number: new FormControl( this.userInfo.passport.number, [], v => (this.userInfo.passport.number = v) ), // … }) // … }); 

يمكنك إضافة FormArray ، والتي بدورها يمكن تمريرها نوع FormControl و / أو إنشاء FormGroup بأكمله كائنات من أي تعقيد وهيكل.
  • FormArray <FormControl>
    FormArray <FormGroup>

    تأخذ FormControl نفسها مجموعة المعلمات التالية في المُنشئ
    • القيمة : TEntity هي القيمة الأولية المكتوبة.
    • المدققون : ValidatorFunctionFormControlHandler [] - مجموعة من المدققين.
    • callbackValidValue : UpdateValidValueHandler | null - وظيفة رد الاتصال التي يتم تمرير آخر قيمة صالحة لها. يتم استدعاء كل مرة تتغير قيمة في FormControl وتمرير هذه القيمة التحقق من الصحة الموصوفة.
    • تنشيط : (() => منطقية) | null - ستقوم الوظيفة بتمكين / تعطيل عمليات التحقق حسب الحالة (يتم تمكينها افتراضيًا بشكل افتراضي). على سبيل المثال ، لا يلزم التحقق من صلاحية تاريخ انتهاء الخدمة إذا لم يتم تحديد مربع الاختيار "غير محدود". نتيجة لذلك ، ببساطة عن طريق إدخال وظيفة هنا للتحقق من حالة الحقل القابل للملاحظة المسؤول عن مربع الاختيار "غير محدود" ، يمكنك إيقاف جميع عمليات التحقق المرتبطة بالحقل للتحقق من التاريخ تلقائيًا ، بدلاً من تسجيل هذا المنطق في كل من عمليات التحقق من حقل التاريخ.
    • extraData: TAdditionalData | null - تسمح لك الكتلة التي تحتوي على معلومات إضافية بإضافة معلومات إضافية إلى FormControl معينة واستخدامها لاحقًا ، على سبيل المثال ، للتصور. يعد هذا ملائمًا إذا كان هناك منشئون لـ FormControl تحتاج إلى تحليل معلومات معينة ، وعدم تمرير هذه المعلومات من خلال حزمة بيانات معقدة إلى عناصر التحكم في التصور. على الرغم من أنني لا أستطيع تقديم سيناريو تطبيق دقيق ولا يمكن إنكاره ، فمن الأفضل أن تتاح لي هذه الفرصة بدلاً من المعاناة بدونها.

    يوجد قيود واحدة لدى Angular FormControl أيضًا ؛ ليست هناك حاجة لإعادة استخدام الكائنات في أشكال مختلفة. أي يمكنك إنشاء منشئ FormGroup وإنشاء كائن خاص بك على كل صفحة. لكن استخدام كائن واحد لكل مجموعة من الصفحات يعد ممارسة سيئة.
    علاوة على ذلك ، يتم تهيئة FormControl بقيمة واحدة ، وإذا تم تغيير هذه القيمة ، فلن تحصل القيمة الجديدة على FormControl . يتم ذلك عن قصد ، لأنه كما أوضح التدريب العملي ، لسبب ما ، يحاول الجميع بعناد تحرير الكائن الأصلي مبدئيًا متجاوزًا عمليات التحقق من الصحة ، وليس القيمة في FormControl . فقط قم بتعيين قيمة جديدة إلى حقل قيمة FormControl لتعديل الكائن الأصلي.
    تقبل FormGroup مجموعة المعلمات التالية في المُنشئ:
    • الضوابط : TControls - كائن موروث من AbstractControls . في الواقع ، فقط قم بإنشاء واجهة موروثة من AbstractControls فيها تعداد الحقول من النوع FormGroup ، FormControl ، FormArray . يمكنك بالطبع تعيين النوع إلى أي ، ولكن بعد ذلك ستفقد جميع مزايا TypeScript .
    • المدققون : ValidatorFunctionFormGroupHandler [] - مجموعة من المدققين لقيم المجموعة. على سبيل المثال ، يمكنك إنشاء FormGroup تحتوي على قيمتين - الحد الأدنى والحد الأقصى للتاريخ ، لعنصر تحكم تحديد الفترة. في هذه المدققات ، ستحتاج إلى تمرير الوظيفة / وظائف التحقق من النطاق الزمني. على سبيل المثال ، لا يكون تاريخ البدء أكبر من تاريخ الانتهاء
    • تنشيط : (() => منطقية) | null - ستقوم الوظيفة بتمكين / تعطيل عمليات التحقق حسب الحالة (يتم تمكينها افتراضيًا بشكل افتراضي). يجب أن يكون مفهوما أن تطبيق وظيفة التحقق من الصحة على مجموعة ما يؤدي إلى تعطيل التحقق من الصحة على مستوى المجموعة بأكملها. على سبيل المثال ، لدينا مربع اختيار لمستند الهوية. يمكنك إنشاء العديد من FormGroups مع مجموعة مختلفة من حقول المستندات: جواز السفر ، رخصة القيادة ، جواز سفر بحار ، إلخ ... في هذه الوظيفة ، تحقق من القيم المنسدلة ، وإذا كانت القيمة المحددة لا تتوافق مع هذه المجموعة ، فسيتم تعطيل جميع عمليات التحقق من الصحة. بتعبير أدق ، سيتم اعتبار المجموعة صالحة ، بغض النظر عن القيم الموجودة فيها.

    دعونا نتحدث عن حقول FormControl ، بما في ذلك وجود FormGroup و FormArray .
    • ControlTypes - أنواع التحكم (Control | Group | Array)
    • معالجة : منطقية - في عملية التحليل. لأن يتم دعم عمليات التحقق غير المتزامنة ، على سبيل المثال ، تلك التي تتطلب طلب خادم. يمكن العثور على الحالة الحالية للفحص في هذا المجال.
      بالإضافة إلى ذلك ، يدعم FormGroup و FormArray طريقة الانتظار ، والتي تتيح لك الانتظار حتى يكتمل التحقق. على سبيل المثال ، عند النقر فوق الزر "إرسال البيانات" ، تحتاج إلى تسجيل التصميم التالي.
       await this.form.wait(); if (this.form.invalid) { … 

    • معطل : منطقي - التحقق من الخطأ معطل (التحكم صالح دائمًا)
    • نشط : منطقي - تمكين التحقق من الخطأ. يعتمد على نتيجة وظيفة التنشيط. هذه القيمة ملائمة جدًا للاستخدام لإخفاء مجموعة من الحقول في نموذج وعدم كتابة وظائف إضافية ومكررة في منطق الأعمال.
    • غير صالح : منطقي ؛ - من أجل FormControl - يعني أن الحقل يحتوي على أخطاء التحقق من الصحة. بالنسبة لـ FormGroup و FormArray ، فهذا يعني إما أن عنصر تحكم المجموعة نفسه يحتوي على أخطاء ، أو أن أحد الحقول المتداخلة (في أي من مستويات التعشيش) يحتوي على أخطاء التحقق من الصحة. أي للتحقق من صحة النموذج بأكمله ، يكفي إجراء فحص واحد غير صحيح أو صالح لمجموعة FormGroup العليا.
    • صالح : منطقي - لـ FormControl - يعني أن الحقل لا يحتوي على أخطاء التحقق من الصحة. بالنسبة لـ FormGroup و FormArray ، فهذا يعني إما أن عنصر تحكم المجموعة نفسه لا يحتوي على أخطاء ولا يحتوي أي من الحقول المتداخلة (في أي مستوى تداخل) على أخطاء التحقق من الصحة.
    • البكر : منطقية - القيمة في الحقل ، بعد التهيئة مع القيمة الافتراضية ، لم تتغير.
    • سيئ : منطقي - القيمة في الحقل ، بعد التهيئة بالقيمة الافتراضية ، تغيرت.
    • لم يمس : منطقي - بالنسبة لـ FormControl - يعني أن الحقل (مثل الإدخال) لم يكن في التركيز. بالنسبة FormGroup و FormArray يعني أن أيا من FormControls المتداخلة كانت في التركيز. تعني قيمة false في هذا الحقل أنه لم يتم تعيين التركيز فقط ، ولكن تمت إزالته أيضًا من الحقل.
    • لمست : منطقي - بالنسبة لـ FormControl - يعني أن الحقل (على سبيل المثال ، الإدخال) كان قيد التركيز. بالنسبة FormGroup و FormArray ، فهذا يعني أن أحد FormControls المتداخلة كان في التركيز. تعني قيمة true في هذا الحقل أن التركيز لم يتم تعيينه فقط ، ولكن تمت إزالته أيضًا من الحقل.
    • التركيز : منطقي - لـ FormControl - يعني أن الحقل (على سبيل المثال الإدخال) هو الآن في التركيز. بالنسبة FormGroup و FormArray ، فهذا يعني أن أحد FormControls المتداخلة الآن في التركيز.
    • الأخطاء : ValidationEvent [] - يحتوي الحقل على أخطاء التحقق من الصحة. بخلاف الحقول المدرجة ، يحتوي هذا الصفيف على أخطاء إما FormControl أو FormGroup أو FormArray ، أي أخطاء هذا التحكم ، وليس كل المتداخلة. يؤثر على حقل صالح / غير صالح
    • تحذيرات : ValidationEvent [] - يحتوي الحقل على رسائل تحذير. بخلاف الحقول المدرجة ، يحتوي هذا الصفيف على أخطاء إما FormControl أو FormGroup أو FormArray ، أي رسائل هذا التحكم ، ولكن ليس كل المرفقة. لا يؤثر على الحقل صالح / غير صالح
    • informationMessages : ValidationEvent [] - يحتوي الحقل على رسائل إعلامية. بخلاف الحقول المدرجة ، يحتوي هذا الصفيف على أخطاء إما FormControl أو FormGroup أو FormArray ، أي رسائل هذا التحكم ، ولكن ليس كل المرفقة. لا يؤثر على الحقل صالح / غير صالح
    • نجاحات : ValidationEvent - يحتوي الحقل على رسائل صلاحية إضافية. بخلاف الحقول المدرجة ، يحتوي هذا الصفيف على أخطاء إما FormControl أو FormGroup أو FormArray ، أي رسائل هذا التحكم ، ولكن ليس كل المرفقة. لا يؤثر على الحقل صالح / غير صالح
    • maxEventLevel () - الحد الأقصى لمستوى رسائل التحقق الموجودة حاليًا في الحقل.
    • ستُرجع الطريقة إحدى قيم التعداد ، في الأولوية التالية.
      1. ValidationEventTypes.Error.
      2. ValidationEventTypes.Warning.
      3. ValidationEventTypes.Info.
      4. ValidationEventTypes.Success.

    • serverErrors : string [] - بعد إرسال رسالة إلى الخادم ، من الجيد التحقق من صحة النموذج على الخادم أيضًا. نتيجة لذلك ، يمكن أن يعرض الخادم أخطاء فحص النموذج النهائي ، ومصفوفة serverErrors مخصصة لهذه الأخطاء. تتمثل الميزة الأساسية لـ serverErrors في التنظيف التلقائي لرسائل التحقق من الصحة عند فقد التركيز من الحقل الذي تم تعيين أخطاء الخادم عليه ، كما يتم مسح أخطاء الخادم إذا تم تغيير الحقل.
    • onChange: مندوب - بالإضافة إلى آلية mobx القياسية - رد فعل ، يمكنك استخدام المفوض وإضافة وظيفة رد اتصال إليها ، والتي تسمى عند تغيير البيانات.
    • setDirty (dirty: boolean): void - تتيح لك الطريقة تغيير قيمة الحقول البكر / القذرة
    • setTouched (لمست: منطقي): باطل؛ - تتيح لك الطريقة تغيير قيمة الحقول التي لم تمسها / المسها
    • تخلص (): باطل ؛ - مطلوب لاستدعاء عنصر التحكم المسؤول عن الصفحة في componentWillUnmount.


    كانت هذه حقول شائعة لجميع عناصر التحكم ، ولكن لكل عنصر تحكم أيضًا حقول فريدة من نوعها.
    FormControl
    • القيمة - تحتوي على القيمة الحالية للحقل. يمكنك أيضًا تعيين قيمة جديدة لهذا الحقل.


    FormGroup و FormArray تحتوي
    • انتظر - تسمح لك الطريقة بتوقع نهاية الاختبارات لكل (عمليات التحقق) بما في ذلك المتداخلة
    • allControls () - تتيح لك هذه الطريقة الحصول على مجموعة كاملة من جميع FormControl بما في ذلك المتداخلة في مستويات مختلفة. أي في الواقع ، يقوم بتوسيع كائن FormGroup متعدد المستويات ، والذي يمكن أن يحتوي أيضًا على FormGroup ، في قائمة واحدة كبيرة تتكون فقط من FormControl. هذه الوظيفة مطلوبة إذا أردنا العثور على أول عنصر غير صالح ووضع التركيز عليه.
      الرمز ، في هذه الحالة ، سيبدو كما يلي:
       await this.form.wait(); if (this.form.invalid) { this.form.setTouched(true); const firstError = this.form.allControls().find(c => c.invalid && !!c.element); if (!!firstError) { firstError.element.focus(); } } ... 



    التصديقات


    بالطبع ، بالإضافة إلى عناصر التحكم التي تسمح لك بالعمل مع البيانات ، نحتاج إلى عمليات تحقق من الصحة. تحتوي حزمة @ quantumart / mobx-form-validation kit بطبيعة الحال على عدد من عمليات التحقق المحددة مسبقًا ، كما تدعم إنشاء عمليات تحقق مخصصة مخصصة.
    مثال على إعداد التحقق من الصحة FormControl لحقل العمر.
     new FormControl<number>( this.userInfo.age, [required(), minValue(18, "    18 .", ValidationEventTypes.Warning)], v => (this.userInfo.age = v) ) 

    يأخذ كل التحقق من الصحة مع أحدث المعلمات:
    • رسالة - رسالة التحقق من الصحة.
    • eventType - مستوى الرسالة. 4 مستويات الرسالة مدعومة.
      1. خطأ - أخطاء
      2. تحذير - تحذيرات
      3. معلومات - رسائل إعلامية
      4. النجاح - رسائل حول صحة. على سبيل المثال ، يمكنك التحقق من أن كلمة المرور معقدة بالفعل.


    تحتوي الحزمة على مجموعة التحقق من الصحة التالية:
    • مطلوب (... - حقل مطلوب
    • notEmptyOrSpaces (... - الحقل غير فارغ ولا يحتوي على مسافات فقط. في الواقع ، مطلوب ، مع الأخذ في الاعتبار حظر المسافات.
    • النموذج (regExp: RegExp ، ... - المعلمة الأولى هي التعبير العادي الذي يجب أن يتطابق معه الحقل. يتم إنشاء خطأ في حالة عدم وجود مطابقة للنمط.
    • invertPattern (regExp: RegExp، ... - المعلمة الأولى هي التعبير العادي الذي يجب ألا يتطابق معه الحقل. يتم إنشاء خطأ إذا كان هناك تطابق في النقش.
    • minLength (minlength: number ، .... - المعلمة الأولى هي الحد الأدنى لطول النص الشامل. يتم إنشاء خطأ إذا كان الطول أقل من الطول المرسل.
    • maxLength (maxlength: number ، .... - المعلمة الأولى هي الحد الأقصى لطول النص الشامل. يتم إصدار خطأ إذا كان الطول أطول من الطول المرسل.
    • absoluteLength (length: number، .... - المعلمة الأولى هي الطول الدقيق للنص. يتم إصدار خطأ إذا كان الطول لا يتطابق مع المحدد المحدد.
    • minValue (min: TEntity | (() => TEntity) ، ... - هذا التحقق من الصحة مخصص للأرقام والتواريخ فقط. يتم تعيين خطأ إذا كانت القيمة أقل من المحدد. خصوصية التحقق هي القدرة على قبول ليس فقط قيمة محددة ، ولكن أيضًا دالة ، مما يعني أنه إذا قرأت القيمة في هذه الوظيفة من الحقلobservable للكائن ، فسيتم إعادة تشغيل التحقق من الصحة نفسه ليس فقط عند تغيير الحقل الذي يتم فيه التحقق من الصحة ، ولكن أيضًا عند تغيير "الحقل المرتبط". أولا يستثنى حقل العلامات وهو يقرأ مثلobservable القيمة.
    • maxValue (max: TEntity | (() => TEntity) ، ... - هذا التحقق من الصحة مخصص للأرقام والتواريخ فقط. يتم تعيين خطأ إذا كانت القيمة أكبر من القيمة المحددة. ميزة التحقق من الصحة هي القدرة على قبول ليس فقط قيمة محددة ، ولكن أيضًا دالة ، مما يعني أنه إذا قرأت القيمة في هذه الوظيفة من الحقلobservable للكائن ، فسيتم إعادة تشغيل التحقق من الصحة نفسه ليس فقط عند تغيير الحقل الذي يتم فيه التحقق من الصحة ، ولكن أيضًا عند تغيير "الحقل المرتبط". أولا باستثناء حقل العلامات وهو يقرأ مثلobservable قيمة
    • notContainSpaces (... - على عكس notEmptyOrSpaces ، سيصدر خطأ إذا كانت القيمة تحتوي على مساحة واحدة على الأقل.
    • مقارنة (تعبير: (value: TEntity) => منطقي (... - كتابة دالة التحقق من الصحة الخاصة بك تولد الكثير من التعليمات البرمجية للنسخ ، تم تطوير هذا المجمع للتخلص من هذه المشكلة. تقبل وظيفة التحقق من الصحة هذه وظيفة كمعلمة أولى ، والتي بدورها تتجاوز القيمة الحالية الحقول ، والتي تتيح لك إجراء فحص معقد ، على سبيل المثال ، حساب التجزئة لرقم TIN أو رقم جواز السفر ، ثم إرجاع true / false ، وسيتم عرض خطأ في حالة إرجاع الاختيار false.
    • isEqual (القيمة: string ... - فحص سلسلة مطابقة بسيط.

    فيما يلي وصف وظائف المجمع التي تتحكم في تدفق مشغلات التحقق من الصحة.
    تجدر الإشارة إلى أن مجموعة عمليات التحقق التي تم تمريرها إلى FormControl و FormGroup و FormArray يتم إطلاقها في صفيف واحد وفي الواقع لا يوجد بها تسلسل تنفيذي . نتيجة لهذا العمل ، سيكون لدينا في مجالات الأخطاء ، والتحذيرات ، والمعلومات ، الرسائل ، صفائف النجاح التي تتكون من أخطاء ، تحذيرات ، مدمجة في صفيف واحد ، إلخ ...
    غالبًا ما يريد العميل رؤية خطأ واحد فقط ، وليس كل ذلك مرة واحدة. علاوة على ذلك ، يمكن تصميم TOR بحيث يتم إجراء فحص واحد فقط بعد مرور الاختبار السابق.
    لحل هذه المشكلة ، يتم استخدام wrapperSequentialCheck . لا تختلف دعوتها وتطبيقها عن المدقق المعتاد للوظيفة ، ولكن عند الإدخال تتلقى مجموعة من أجهزة التحقق من الصحة التي سيتم إطلاقها بالتتابع ، أي يبدأ التحقق من الصحة التالي فقط بعد مرور السابقة دون أخطاء.
    وظيفة المجمع الثانية هي وظيفة التحكم في التدفق لعمليات التحقق من الصحة. wrapperActivateValidation حيث أن المعلمة الأولى تأخذ وظيفة يجب فيها كتابة شروط تنشيط التحقق من الصحة. بخلاف وظيفة التنشيط التي يتم تمريرها إلى FormControl ، تم تصميم هذا الاختيار لمنطق أكثر تعقيدًا. افترض أن لدينا منشئًا مشتركًا لطريقة الدفع FormGroup بالكامل ، علاوة على ذلك ، هناك طريقة واحدة فقط على الخادم تقبل مجموعة شائعة من الحقول. لكن المهم هو أنه على الرغم من أن النموذج واحد ، بناءً على "نوع الدفع" ، فإننا نعرض مجموعة مختلفة من الحقول للمستخدم. لذلك يتيح لك wrapperActivateValidation أن تكتب المنطق الذي سيتم فيه إجراء العديد من الشيكات وفقًا لنوع الدفع.
    سيبدو استخدام الأغلفة مثل الوظائف العادية.
     new FormControl( this.userInfo.megapole, [wrapperActivateValidation(() => this.info.A === 10, [ required(), pattern(/\^d{10}$/) ]), wrapperActivateValidation(() => this.info.A === 20, [ wrapperSequentialCheck([ notContainSpaces(), pattern(/\^d{20}$/) ]) ])], v => (this.userInfo.megapole = v) ) 

    يوضح هذا المثال أنه سيتم إجراء عمليات التحقق المطلوبة () ، والنمط (/ \ ^ d {10} $ /) فقط مع this.info.A === 10 ، وإذا كان هذا. info.A === 20 ، ثم notContainSpaces () ، ستعمل عمليات التحقق من الصحة (/ \ ^ d {20} $ /) ، بالإضافة إلى ذلك ، ستعمل عمليات التحقق هذه بالتسلسل ، على عكس الحالة الأولى.

    بطبيعة الحال ، ستأتي اللحظة التي تكون فيها مجموعة التحقق من الصحة القياسية غير كافية.
    ثم عليك أن تكتب وظائفك غير المتزامنة. لحسن الحظ ، يتم ذلك دون أي صعوبات خاصة.
    تم شحذ FormControl في الأصل من خلال وظائف التحقق من الصحة غير المتزامنة ، والتي قد ترغب في الانتقال إلى الخادم للحصول على البيانات ، ويجب أن تنتظر هذه الإجابة. ونتيجة لذلك ، تكون جميع عمليات التحقق من الصحة غير متزامنة.
     async function checkValueOnServer(control: FormControl): Promise<ValidationEvent[]> { if (control.value == null) { return []; } const result = await sendToServer(control.value); if (result.errorMessage) { return [ { message: result.errorMessage, type: ValidationEventTypes.Error, }, ]; } return []; } 

    هنا تحتاج إلى الانتباه إلى كائنين.
    أولاً نمانع دائمًا بالصفيف. أي في الواقع ، يمكنك إرجاع عدة رسائل خطأ مرة واحدة ، إذا كنت ترغب في ذلك.
    النقطة الثانية هي الكائن المرتجع ؛ فهي تحتوي على مجموعة الحقول التالية.
    • key ؟: string - حقل اختياري ، يسمح لك بتحديد "مفتاح" للتحقق من الصحة. بالنسبة لجميع المفاتيح الأساسية ، يكون المفتاح فريدًا ويطابق اسمه. قد ترغب في استخدام المفتاح لتقديم القائمة كرد فعل ، ولكن كما أظهرت الممارسة ، هذه فكرة سيئة. في المستقبل ، على سبيل المثال ، سأظهر أنه من الأفضل استخدام الرسائل ، وعدم لمس المفتاح على الإطلاق. في أي حال ، هو ، كما هو الحال في Angunar ، ولكن تم تخفيض حاجتها ، في الواقع ، إلى 0.
    • الرسالة : سلسلة - رسالة التحقق من الصحة. مجال إلزامي.
    • النوع : ValidationEventTypes - نوع الرسالة.
      1. خطأ - أخطاء
      2. تحذير - تحذيرات
      3. معلومات - رسائل إعلامية
      4. النجاح - رسائل حول صحة. على سبيل المثال ، يمكنك التحقق من أن كلمة المرور معقدة بالفعل.

    • extraData ؟: أي - معلومات إضافية يمكن إرسالها مع التحقق من الصحة ، إذا لزم الأمر. يمكن أن يكون بعض العلامات أتش تي أم أل إضافية أو نمط معين. بشكل عام ، يمكنك وضع كل شيء في أي.


    ملحقات


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

    بالنسبة للإدخال ، سيبدو الارتباط الخاص بالعنصر FormControl (الاسم) بهذا الشكل.
    <input type = "text" {... InputFormControl.bindActions (controls.name)} />
    بالنسبة textarea ، سيكون الربط مثل هذا
    <textarea {... TextAreaFormControl.bindActions (controls.name)} />

    قبول InputFormControl.bindActions و TextAreaFormControl.bindActions معلمتين:
    • formControl : FormControl - في الواقع FormControl والتي سيتم استخدامها للربط. المطلوبة.
    • الأحداث ؟ - معلمة اختيارية تحتوي على قائمة بالوظائف التي يمكن استدعاؤها إذا كنت بحاجة إلى تخصيصها. , bindActions - Element, , element FormControl -, . . event. .
      • ref
      • onChange
      • onBlur
      • onFocus


    , FormControl - .
     this.form = new FormGroup<IUserInfo>({ name: new FormControl( this.userInfo.name, [], v => (this.userInfo.name = v) ) }); 

    this.userInfo.name , FormControl . FormControl.for
     this.form = new FormGroup<IUserInfo>({ name: FormControl.for(this.userInfo, 'name', []) }); 

    , name name . , TypeScript, name , . userInfo — .

    — . :)

    مثال


    React TypeScript mobx.
    .
    npm install @quantumart/mobx-form-validation-kit

    ,
    :

    ,
    npm init –y
    npm install --save-dev webpack webpack-cli
    npm install --save react react-dom
    npm install --save-dev @types/react @types/react-dom
    npm install --save-dev typescript ts-loader source-map-loader


    tsconfig.json
     { "compilerOptions": { "outDir": "./dist/", "sourceMap": true, "noImplicitAny": true, "module": "commonjs", "target": "es6", "jsx": "react", "experimentalDecorators": true, "emitDecoratorMetadata": true } } 


    • src\components\Hello.tsx
    • src\index.tsx
    • index.html
    • src\assets\global.scss


    src\components\ Hello.tsx
     import * as React from "react"; export class Hello extends React.Component { render() { return ( <h1> Hello from TypeScript and React! </h1> ); } } 

    src\ index.tsx
     import * as React from "react"; import * as ReactDOM from "react-dom"; import { Hello } from "./components/Hello"; ReactDOM.render( <Hello />, document.getElementById("example") ); 

    index.html
     <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> </head> <body> <div id="example"></div> <!-- Dependencies --> <script src="./node_modules/react/umd/react.development.js"></script> <script src="./node_modules/react-dom/umd/react-dom.development.js"></script> <!-- Main --> <script src="./dist/main.js"></script> </body> </html> src\assets\global.scss .row { display: inline; } 



    webpack-dev-server
    npm install --save-dev webpack-dev-server
    npm install --save-dev awesome-typescript-loader
    npm install --save-dev html-webpack-plugin

    webpack.config.js
     const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/index.tsx', resolve: { extensions: ['.ts', '.tsx', '.js'] }, output: { path: path.join(__dirname, '/dist'), filename: 'bundle.min.js' }, module: { rules: [ { test: /\.tsx?$/, loader: 'awesome-typescript-loader' }, { test: /\.(scss|css)?$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { importLoaders: 1, }, }, { loader: 'sass-loader', options: { sourceMap: true } }, ], }, ] }, plugins: [ new HtmlWebpackPlugin({ template: './index.html' }) ] } 

    , mobx React.
     "mobx": "4", "mobx-react": "^6.1.1", 

    C IE10 mobx, 4 , package.json.

      "style-loader": "^0.23.1", "css-loader": "^3.1.0", "node-sass": "^4.12.0", "sass-loader": "^7.1.0" 


    npm install

    , .
    npm install @quantumart/mobx-form-validation-kit



    package.json
     { "name": "ttt", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "webpack-dev-server --mode development --open", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "MIT", "devDependencies": { "@types/react": "^16.9.5", "@types/react-dom": "^16.9.1", "awesome-typescript-loader": "^5.2.1", "html-webpack-plugin": "^3.2.0", "source-map-loader": "^0.2.4", "ts-loader": "^6.2.0", "typescript": "^3.6.3", "webpack": "^4.41.0", "webpack-cli": "^3.3.9" }, "dependencies": { "@quantumart/mobx-form-validation-kit": "^1.0.8", "mobx": "4", "mobx-react": "^6.1.1", "react": "^16.10.2", "react-dom": "^16.10.2", "webpack-dev-server": "^3.8.2", "style-loader": "^0.23.1", "css-loader": "^3.1.0", "node-sass": "^4.12.0", "sass-loader": "^7.1.0" } } 


    npm run start


    Hello from TypeScript and React!


    Hello . RegistrationStore RegistrationStore.ts
    src\RegistrationStore.ts
     import { observable } from "mobx"; export class RegistrationStore { @observable public userInfo = { name: "" }; } export const registrationStore = new RegistrationStore(); 

    Hello.ts, .
     import * as React from "react"; import { observer } from "mobx-react"; import { registrationStore } from "../RegistrationStore"; @observer export class Hello extends React.Component { private changeName = (event: React.ChangeEvent<HTMLInputElement>) => { registrationStore.userInfo.name = event.target.value; }; render() { return ( <React.Fragment> <h1>, {registrationStore.userInfo.name}</h1> <div className="row"> <span>:</span> <input type="text" value={registrationStore.userInfo.name} onChange={this.changeName} /> </div> </React.Fragment> ); } } 

    , Store Mobx. input.
    , . , . «» . , .

    @quantumart/mobx-form-validation-kit

    - .
    stc/ErrorWraper.tsx
     import * as React from "react"; import { observer } from "mobx-react"; import { FormControl } from "@quantumart/mobx-form-validation-kit"; interface Props { formControl: FormControl; } @observer export class ErrorWraper extends React.Component<Props> { render() { return ( <div> {this.props.children} {this.props.formControl.errors.map(error => ( <span key={error.message} className="error"> {error.message} </span> ))} </div> ); } } 

    , -, .

    Hello.tsx .
    - — changeName. {...InputFormControl.bindActions(controls.name)} . .
    - – input, input , , , .
    - – form store , , , componentWillUnmount registrationStore.form.dispose() . mobx FromControl .
     import * as React from "react"; import { observer } from "mobx-react"; import { registrationStore } from "../RegistrationStore"; import { ErrorWraper } from "../ErrorWraper"; import { InputFormControl } from "@quantumart/mobx-form-validation-kit"; @observer export class Hello extends React.Component { constructor(props: any) { super(props); registrationStore.initForm(); } componentWillUnmount() { registrationStore.form.dispose(); } render() { const controls = registrationStore.form.controls; return ( <React.Fragment> <h1>, {registrationStore.userInfo.name}</h1> <div className="row"> <span>:</span> <ErrorWraper formControl={controls.name}> <input type="text" {...InputFormControl.bindActions(controls.name)} /> </ErrorWraper> </div> </React.Fragment> ); } } 

    RegistrationStore.ts.
    .
    ( ) userInfo, form. - userInfo.
     import { observable } from "mobx"; import { FormControl, FormGroup, AbstractControls } from "@quantumart/mobx-form-validation-kit"; interface IUserInfo extends AbstractControls { name: FormControl; } export class RegistrationStore { @observable public userInfo = { name: "" }; @observable public form: FormGroup<IUserInfo>; public initForm(): void { this.form = new FormGroup<IUserInfo>({ name: new FormControl( this.userInfo.name, [], v => (this.userInfo.name = v) ) }); } } export const registrationStore = new RegistrationStore(); 

Source: https://habr.com/ru/post/ar470537/


All Articles