1. 텍스트 폼 필드 설정
TextFormField(
minLines: 1, // 최소 줄 수
maxLines: null, // 무제한으로 아래로 확장
keyboardType: TextInputType.multiline, // 여러 줄 입력 가능하게 설정
),
TextFormField(),
그냥 텍스트폼필드와, 텍스트 폼필드를 설정할 수 있다.

위의 필드는 글이 늘어나면 아래로 확장되고
아무 설정을 하지 않으면 옆으로 늘어난다.
2. 텍스트 폼에 체크 박스 넣기


Checkbox(
value: false,
onChanged: (value) {
print(value);
},
),
체크박스를 누를 때 마다 값을 출력하도록 했다.
체크를 하더라도 체크 상태가 유지되지 않고, 계속해서
true
가 출력된다.
원래라면 눌렀을때 true → false → true 라는 식으로 계속해서 변경되는 것이 옳다.이를 위해
StatelessWidget
을 ful 로 변경을 해야할까..?(참고로
TextEditingController
는 체크박스에서는 사용 할 수 없다.)3. Expanded 와 Flexible

빨간 박스만큼 Expanded 하고 있다.

Flexible
을 loose 로 설정해 주어야 유연하게 공간을 차지한다. (스크롤도 가능함) TextFormField(
controller: _username,
),
TextFormField(
controller: _password,
),
],
),
),
TextButton(
onPressed: () {
print(_username.text); //I/flutter (12998): sarr
},
child: Text("글쓰기")),
],
),
username 은 값을 가져올 수 있다.
view 는 viewModel 한테 의존하기 때문에 이 값을 vm 에 전달 해야한다.

요청되면 이걸 리턴함
Future<void> notifySave() async {
Map<String, dynamic> one = await PostRepository().save(); // 한 건 받음
_Post newPost = _Post.fromMap(one);
PostListModel model = state!; // 이게 호출될때는 리스트->글쓰기 로 간거라 null 일 수가 없음
model.posts.add(newPost);
state = PostListModel(model.posts);
}
껍데기를 바꿨기 때문에 이게 넣어진다(주소가 달라짐)
Future<void> notifySave() async {
Map<String, dynamic> one = await PostRepository().save(); // 한 건 받음
_Post newPost = _Post.fromMap(one);
PostListModel model = state!; // 이게 호출될때는 리스트->글쓰기 로 간거라 null 일 수가 없음
List<_Post> newPosts = [newPost, ...model.posts]; //최근에 쓴 글이 앞에 와야해
state = PostListModel(newPosts);
}
혹은 깊은 복사를 해서 넣어야 한다.
그러나 state 에 model 을 바로 넣을 수는 없다. (기존의 값을 건들이게 되기 떄문에)
리뷰
Future<void> notifySave(String title, String contnent) async {
// 통신코드
Map<String, dynamic> one =
await PostRepository().save(title, contnent); // 한 건 받음
_Post newPost = _Post.fromMap(one);
PostListModel model = state!; // 이게 호출될때는 리스트->글쓰기 로 간거라 null 일 수가 없음
//model.posts.add(newPost);
// 상태 갱신 코드
List<_Post> newPosts = [newPost, ...model.posts]; //최근에 쓴 글이 앞에 와야해
state = PostListModel(newPosts);
}
- repository
Future<Map<String, dynamic>> save(String title, String content) async {
Response response = await dio.post(
"/api/post",
data: {"title": title, "content": content},
);
Map<String, dynamic> responseBody = response.data["body"];
// list 의 map 타입
return responseBody;
}
- write_body
TextButton(
onPressed: () {
ref
.read(postListProvider.notifier)
.notifySave(_title.text, _content.text);
},
child: Text("글쓰기")),
],
글쓰기 버튼을 누른 뒤 직접 뒤로가기 버튼을 눌러 보면 작성된 게시물이 업로드 되어 있다.
글 쓰기 버튼을 누르고 나면 어디선가
Navigator.pop(context)
를 해야 하는것..
이 페이지에서는 write 페이지가 날아간다고 해서 model 이 사라지진 않기 때문에 상관 없지만 어떤 페이지에서는 리턴이 오래 걸릴 때 이미 List로 갔지만, 작성 시도한 게시글은 보이지 않고, 몇 초 뒤에 나타나게 될 수 있다.따라서 작성등록 → List로 이동은 하나의 트랜잭션으로 묶여 있어야 한다.
notifySave
는 이미 async~await 를 갖고 있다. 그렇다면 save 의 마지막에 pop 을 시키면 될까…?
매개변수로는 title과 content 만 갖고 있으면 된다…

창고 만들 떄 만들어
작동 원리는 main 에
navigatorKey: navigatorKey,
를 넣어놨다 . 이 키는 utils
에서 전역 키로 만들어져 있다.(임의로 등록해놓음)
final navigatorKey = GlobalKey<NavigatorState>();
제일 상단에 떠있는 페이지를 추적할 수 있도록 해주는 것이다.

이제 ViewModel(=VM) 에 만들어 놓은 컨텍스트를 보면
final mContext = navigatorKey.currentState!.context;
절대 null 이 아닐 것이란것을 가정한다. Save 가 호출되는 곳은
write 페이지이기 때문에 context 가 존재하지 않을 수 없는것이다.
따라서 전역변수로 추적되는 context 를 매개변수로 받아
화면 이동이 이루어지게 되는 것이다.
- 서버 통신 - jar 파일 만들기 / 설정 https://inblog.ai/hj/서버-통신하기1-설정-31514
- 서버 통신 - 상세 페이지 보기 https://inblog.ai/hj/서버-통신하기2-상세-페이지-보기-31515
- 서버 통신 - 글쓰기 https://inblog.ai/hj/서버-통신하기3-글쓰기-31518
- 서버 통신 - 게시글 삭제 https://inblog.ai/hj/서버-통신하기4-게시글-삭제-31519
Share article