#flutter #validation #dart #textformfield
Вопрос:
Мне интересно, могу ли я передать функцию в качестве валидатора. Я пытался, но безрезультатно.
Widget Field(String changedValue, String label, bool isTextObscured) {
return TextFormField(
decoration: InputDecoration(labelText: label),
validator: checkFieldEmpty,
);
}
checkFieldEmpty(String fieldContent) {
if(fieldContent.isEmpty) {
return 'Ce champ est obligatoire.';
}
return null;
}
Комментарии:
1. Да, вы можете, но
fieldContent
должны быть аннулированы. ЗаменитьString
наString?
. Кроме того, укажите тип возвращаемойcheckFieldEmpty
функцииString?
, как указано в ответах ниже.
Ответ №1:
Возможно, тип возврата функции должен быть String?
таким, чтобы он соответствовал прототипу валидатора!
Widget Field(String changedValue, String label, bool isTextObscured) {
return TextFormField(
decoration: InputDecoration(labelText: label),
validator: checkFieldEmpty,
);
}
String? checkFieldEmpty(String? fieldContent) { //<-- add String? as a return type
if(fieldContent.isEmpty) {
return 'Ce champ est obligatoire.';
}
return null;
}
Более подходящий способ сделать это в Flutter
Помните, что flutter-это декларативный язык. То есть вы создаете свое приложение, составляя дерево виджетов. Здесь вы используете функцию для возврата виджета. Это нарушает это правило. Вместо этого вы должны объявить свой собственный пользовательский виджет, который реализует TextField
виджет. Вот как:
1. Объявите свой пользовательский виджет
// Declare your CustomTextField as a Stateless/Stateful Widget
class MyCustomTextField extends StatelessWidget {
// Declare your custom vars, including your validator function
final String? changedValue;
final String? label;
final bool? isTextObscured;
final String? Function(String?)? validator;
const MyCustomTextField({
Key? key,
this.changedValue,
this.label,
this.isTextObscured,
this.validator,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return TextFormField(
decoration: InputDecoration(labelText: label),
validator: validator,
);
}
}
2. Используйте свой собственный виджет
Теперь вы можете использовать этот пользовательский виджет в качестве дочернего элемента любого другого виджета:
class ParentWidget extends StatelessWidget {
const ParentWidget({Key? key}) : super(key: key);
// This is your custom validator function and can leave
// anywhere ;)
Stirng? customValidtaor(String? fieldContent) => fieldContent.isEmpty? 'Ce champ est obligatoire.': null
@override
Widget build(BuildContext context) {
return MyCustomTextField(
label: 'Some label'
// declare the validator here...
// valiator: (fieldContent) => fieldContent.isEmpty? 'Ce champ est obligatoire.': null
// or use your custom validator function
validator: customValidator,
);
}
}
Делая это, вы уважаете лучшие практики Flutter, используя композицию виджетов 😉
Комментарии:
1. Я боюсь, что это все еще не работает… «Тип аргумента ‘Строка? Функция(строка)’ не может быть присвоена типу параметра ‘Строка? Функция(строка?)?’.»
2. да, просто обновите функцию:
String? function(String? fieldContent){/*...*/}
извините, что я пропустил тип аргумента. Я соответствующим образом обновил свой ответ 😉
Ответ №2:
Добавьте строку в качестве типа возврата для метода checkFieldEmpty (), см. Ниже
вместо этого это:
checkFieldEmpty(String fieldContent) {}
используйте это:
String checkFieldEmpty(String fieldContent) {}
Полный Пример Кода:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final appTitle = 'Form Validation Demo';
return MaterialApp(
title: appTitle,
home: Scaffold(
appBar: AppBar(title: Text(appTitle)),
body: MyCustomForm(),
),
);
}
}
// Create a Form widget.
class MyCustomForm extends StatefulWidget {
@override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
// Create a corresponding State class.
// This class holds data related to the form.
class MyCustomFormState extends State<MyCustomForm> {
// Create a global key that uniquely identifies the Form widget
// and allows validation of the form.
//
// Note: This is a GlobalKey<FormState>,
// not a GlobalKey<MyCustomFormState>.
final _formKey = GlobalKey<FormState>();
Widget textField(String changedValue, String label, bool isTextObscured) {
return TextFormField(
decoration: InputDecoration(labelText: label),
validator: checkFieldEmpty,
);
}
String checkFieldEmpty(String fieldContent) {
if (fieldContent.isEmpty) return 'Ce champ est obligatoire.';
return null;
}
@override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
textField('changedValue', 'Enter Password', false),
ElevatedButton(
onPressed: () {
// Validate returns true if the form is valid, or false otherwise.
if (_formKey.currentState.validate()) {
// If the form is valid,
// perform further actions here
}
},
child: Text('Submit'),
),
],
),
);
}
}