반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Axon framework
- 스프링
- JPA
- nestjs공부
- 코테준비
- JPA 공부
- JPA공부
- 스프링부트
- 기술공부
- 알고리즘공부
- nestjs스터디
- 자바공부
- K8S
- querydsl
- Kafka
- 카프카
- 스프링공부
- DDD
- 코테공부
- JPA예제
- 스프링 공부
- 스프링부트공부
- 프로그래머스
- 기술면접공부
- 플러터 개발
- 플러터 공부
- 자료구조공부
- nestjs
- Flutter
- JPA스터디
Archives
- Today
- Total
DevBoi
[Flutter] Form 빌더 동적 생성하기 본문
반응형
FormBuilder는 폼을 관리하기 위해 편하게 제공해주는 모듈이다.
특정 액션시 Form의요소를 동적으로 변경해보자
우선 동적 요소 추가를 해주기 위한, 위젯이다.
Expanded(
child: MaterialButton(
color: Theme.of(context).colorScheme.secondary,
child: const Text(
"Add Score",
style: TextStyle(color: Colors.white),
),
onPressed: () {
setState(() {
fields.add(
NewScore(
name: 'score_${fields.length}',
));
});
},
),
),
해당 버튼을 클릭하면, fields에 NewScore라는 위젯이 추가가 된다.
그리고 삭제를 하면? Widget List에서 마지막 원소를 빼준다.
Expanded(
child: MaterialButton(
color: Theme.of(context).colorScheme.secondary,
child: const Text(
"Dec Score",
style: TextStyle(color: Colors.white),
),
onPressed: () {
setState(() {
fields.removeAt(fields.length - 1);
});
},
),
),
위는 remove시키는 모듈이다.
무튼 이렇게 하고, FormBuilder안에서 감싸주면, 해당 위젯에 대한 정보가 Json stringify 되서 저장된다.
class NewScore extends StatelessWidget {
const NewScore({
super.key,
required this.name,
});
final String name;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: [
Expanded(
child: FormBuilderTextField(
name: name,
validator: FormBuilderValidators.numeric(errorText: 'score is number'),
decoration: const InputDecoration(
label: Text('Score'),
),
),
),
],
),
);
}
}
생성되는 newScore는 이렇다.
해당 객체가 그냥 단순히 반복되는 것이다.
뭐 사실 데모용으로 시현을 위해 필요한 부분이라, 디자인이나 별도 신경은 쓰지않았다.
단순히 위젯 추가 삭제 관리, Form으로 동적 대응이 전부이다.
아래는 전체 소스이다.
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
class CreatePopup extends StatefulWidget {
@override
State<CreatePopup> createState() => _CreatePopupState();
}
class _CreatePopupState extends State<CreatePopup> {
final _formKey = GlobalKey<FormBuilderState>();
final List<Widget> fields = [];
String savedValue = '';
var subjectList = ['수학', '영어', '체육'];
@override
void initState() {
savedValue = _formKey.currentState?.value.toString() ?? '';
super.initState();
}
@override
Widget build(BuildContext context) {
return FormBuilder(
key: _formKey,
// IMPORTANT to remove all references from dynamic field when delete
clearValueOnUnregister: true,
child: Column(
children: <Widget>[
const SizedBox(height: 20,),
FormBuilderDropdown<String>(
name: 'subject',
decoration: InputDecoration(
labelText: "subject"
),
items: subjectList.map((subject) => DropdownMenuItem(
alignment: AlignmentDirectional.center,
value: subject,
child: Text(subject),
)).toList(),
valueTransformer: (val) => val?.toString(),
),
FormBuilderTextField(
name: 'small-subject',
validator: FormBuilderValidators.required(errorText: 'small-subject is required!!'),
decoration: const InputDecoration(
label: Text('small-subject'),
),
),
...fields,
const SizedBox(height: 10),
Row(
children: <Widget>[
const SizedBox(width: 20),
Expanded(
child: MaterialButton(
color: Theme.of(context).colorScheme.secondary,
child: const Text(
"Add Score",
style: TextStyle(color: Colors.white),
),
onPressed: () {
setState(() {
fields.add(
NewScore(
name: 'score_${fields.length}',
));
});
},
),
),
Expanded(
child: MaterialButton(
color: Theme.of(context).colorScheme.secondary,
child: const Text(
"Dec Score",
style: TextStyle(color: Colors.white),
),
onPressed: () {
setState(() {
fields.removeAt(fields.length - 1);
});
},
),
),
],
),
MaterialButton(
color: Theme.of(context).colorScheme.secondary,
height: 30,
child: const Text(
"Save",
style: TextStyle(color: Colors.white),
),
onPressed: () {
_formKey.currentState!.saveAndValidate();
setState(() {
savedValue =
_formKey.currentState?.value.toString() ?? '';
print(savedValue.toString());
});
},
),
// const Divider(height: 20),
// Text('Saved value: $savedValue'),
],
),
);
}
}
class NewScore extends StatelessWidget {
const NewScore({
super.key,
required this.name,
});
final String name;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: [
Expanded(
child: FormBuilderTextField(
name: name,
validator: FormBuilderValidators.numeric(errorText: 'score is number'),
decoration: const InputDecoration(
label: Text('Score'),
),
),
),
],
),
);
}
}
반응형
'[Mobile] > [Flutter]' 카테고리의 다른 글
[Flutter] 팝업 구현 (0) | 2023.08.26 |
---|---|
[Flutter] 다양한 FormBuilder,FormValidator (0) | 2023.08.26 |
[Flutter] TabBar 구현 및 위젯 간 데이터 생성자 (0) | 2023.08.23 |
[Flutter] material 앱 샘플 팁 (0) | 2023.08.23 |
[Flutter] Search Module (2) | 2023.08.20 |