서버 통신하기-3. 글쓰기

HootJem's avatar
Oct 14, 2024
서버 통신하기-3. 글쓰기

1. 텍스트 폼 필드 설정

TextFormField( minLines: 1, // 최소 줄 수 maxLines: null, // 무제한으로 아래로 확장 keyboardType: TextInputType.multiline, // 여러 줄 입력 가능하게 설정 ), TextFormField(),
그냥 텍스트폼필드와, 텍스트 폼필드를 설정할 수 있다.
 
notion image
위의 필드는 글이 늘어나면 아래로 확장되고 아무 설정을 하지 않으면 옆으로 늘어난다.
 

2. 텍스트 폼에 체크 박스 넣기

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

3. Expanded 와 Flexible

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

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 을 시키면 될까…?
 
notion image
매개변수로는 title과 content 만 갖고 있으면 된다…
notion image
창고 만들 떄 만들어
 
작동 원리는 main 에 navigatorKey: navigatorKey, 를 넣어놨다 . 이 키는 utils 에서 전역 키로 만들어져 있다.(임의로 등록해놓음) final navigatorKey = GlobalKey<NavigatorState>();
제일 상단에 떠있는 페이지를 추적할 수 있도록 해주는 것이다.
notion image
 
이제 ViewModel(=VM) 에 만들어 놓은 컨텍스트를 보면
final mContext = navigatorKey.currentState!.context;
절대 null 이 아닐 것이란것을 가정한다. Save 가 호출되는 곳은 write 페이지이기 때문에 context 가 존재하지 않을 수 없는것이다. 따라서 전역변수로 추적되는 context 를 매개변수로 받아 화면 이동이 이루어지게 되는 것이다.
 

Share article

[HootJem] 개발 기록 블로그