フロント側をFlutter(スマホ)Thymeleaf(PC)、バックエンド側SpringBootの自動作成勉強中
8:55
①昨日の、『並び順を忘れてた。ので、割と簡単そうな、並び順を作っている。まず、Flutter側画面』の続き。そこそこ出来上がったので。
・昨日日記に上げたスマホ画面と、あれから、作りこんだスマホ画面(メールアドレスで昇順時の画面)とPC.WEB画面での表示
■昨日日記に上げたスマホ画面
■あれから、作りこんだスマホ画面(メールアドレスで昇順時の画面)▲▼が追加した。わかりやすくなっていると思う。
■PC.WEB画面での表示。WEB画面ではタイトル行を押下することにより▲▼を変えることができるが、スマホは、ちょっとちがうかなと思ってドロップダウンリストにしました。
・ちょっと難しかった箇所
・ドロップダウンリストに並び順▲、▼を追加したら、バックエンド側のレスポンスに反応しなかったりして、手こずった。結局DropdownButtonを『 items: getItems(_selectItem, _userSrchForm.sortOrder),』にしたら動的にドロップダウンリストが書き換わった。
DropdownButton( items: getItems(_selectItem, _userSrchForm.sortOrder), value: _selectItem,
②これが、ドロップダウンリストFlutter側抜粋
class _UserListState extends State<UserList> { ・・・ final List<String> _selectItems = ["id", "name", "email", "roles", "enableFlag"]; final List<String> _selectItemNames = ["ID", "名前", "メールアドレス", "ロール", "可否フラグ"]; int _selectItem = 0; ・・・ Widget build(BuildContext context) { ・・・ body: Form( key: _formKey, child : ListView( controller: _scrollController, children: _makeWidgets(), ), ), ・・・ } List<Widget> _makeWidgets() { if (_selectedIndex == 0) { return _makeCndsWidgets(); } else { return _makeListWidgets(); } } ・・・ List<Widget> _makeListWidgets() { ・・・ // 並び順選択 contentWidgets.add(Center( child:Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text("並び順 : ", overflow: TextOverflow.clip, ), DropdownButton( items: getItems(_selectItem, _userSrchForm.sortOrder), value: _selectItem, icon: const Icon(Icons.arrow_downward), elevation: 16, style: const TextStyle(color: Colors.deepPurple), underline: Container( height: 2, color: Colors.deepPurpleAccent, ), onChanged: (value) { setState(() { // 違う項目名が選択された場合、並び順は””にする if (value != _selectItem) { _userSrchForm.sortOrder = ""; } _selectItem = value as int; _userSrchForm.sortItemName= _selectItems[_selectItem]; // 情報一覧リストへ、list_up_dwnで、httpアクセス httpForListUpDwn(); }); }, ), ]), ), ); ・・・ return contentWidgets; } /// 並び順のドロップダウンリストを作成する List<DropdownMenuItem<int>> getItems(int selectItem, String sortOrder) { List<DropdownMenuItem<int>> _items = <DropdownMenuItem<int>>[]; String _nameWk = ""; for (int i = 0; i < _selectItemNames.length; i++) { if (selectItem == i) { _nameWk = _selectItemNames[i] ; if (sortOrder == 'D') { _nameWk += '▼'; } else if (sortOrder == 'A') { _nameWk += '▲'; } } else { _nameWk = _selectItemNames[i]; } _items.add(DropdownMenuItem( value: i, child: Text(_nameWk), )); } return _items.toList(); } void initState() { super.initState(); ・・・ // 並び順指定があればドロップダウンリストはそれにする。 if (_userSrchForm.sortItemName == "") { _selectItem = 0; } else { for (int i = 0; i < _selectItems.length; i++) { if (_selectItems[i] == _userSrchForm.sortItemName) { _selectItem = i; break; } } } }
③そして、これがhttpのFlutter側抜粋
/// 情報一覧リストへ、list_up_dwnで、httpアクセス void httpForListUpDwn() { httpForList("list_up_dwn", "http://192.168.1.13:8080/members/admin/user/userA/list_up_dwn"); } /// 情報一覧リストへのhttpアクセス void httpForList(String _mode, String _url) async { try { // TextFormField値を、Formに設定。補足:TextFormField以外は直接Formを見ている。 _userSrchForm.fromUserSrchFormController(_nameController, _emailController ); String _userSrchFormJson = _userSrchForm.toJson(_mode, "${widget.cookies['XSRF-TOKEN']}"); widget.headers["content-type"]= "application/json; charset=UTF-8"; final url = Uri.parse(_url); http.Response response = await http.post(url,headers: widget.headers, body: _userSrchFormJson); if (response.statusCode != 200) { // 検索(エラーメッセージ欄がある)表示 _selectedIndex = 0; setState(() { int statusCode = response.statusCode; if (response.statusCode == 401) { _errorSuccessMsg = "ログインしてください"; } else { _errorSuccessMsg = "エラーが発生しました $statusCode"; } }); // 画面を先頭に戻す _scrollController.animateTo(0, duration: const Duration(milliseconds:600), curve: Curves.easeInQuint); return; } CommUtils.updateCookie(response, widget.cookies, widget.headers); // response.bodyをutf8でdecodeする。 String _resData = utf8.decode(response.body.runes.toList()); if (kDebugMode) { print(_resData); } // バックエンドで例外発生の場合MessageFormの値しか戻らないため、ここで確認する MessageForm _messageForm = MessageForm.initData(); _messageForm.fromJson(_resData); // SpringBootで例外発生の場合 if (_messageForm.mode =="SystemError") { // エラー画面 Navigator.of(context).push( MaterialPageRoute( builder: (context) => Error(title: widget.title, username: widget.username, headers: widget.headers, cookies: widget.cookies, resData: _resData), ), ); // 正常処理 } else { setState(() { // 検索結果リスト表示 _selectedIndex = 1; _userSrchForm.fromJson(_resData); // From値を、TextFormFieldに設定する。補足:TextFormField以外は直接Formを見ている。 _userSrchForm.forUserSrchFormController(_nameController, _emailController ); _errorSuccessMsg = _userSrchForm.errorMessage + _userSrchForm.successMessage; // 並び順指定があればドロップダウンリストはそれにする。 if (_userSrchForm.sortItemName == "") { _selectItem = 0; } else { for (int i = 0; i < _selectItems.length; i++) { if (_selectItems[i] == _userSrchForm.sortItemName) { _selectItem = i; break; } } } }); } } on Exception catch (e) { setState(() { _errorSuccessMsg = "エラーが発生しました" + e.toString(); }); } // 画面を先頭に戻す _scrollController.animateTo(0, duration: const Duration(milliseconds:600), curve: Curves.easeInQuint); _myFocusNode.requestFocus(); }
④これがSpringBootバックエンドがわのController抜粋
・PC・スマホ向け共通Controller
public class UserCommController { ・・・ /** * リターン共通処理(Flutter、PC・WEB共用) * リターン共通処理 * * @param url 遷移先 * @param model モデル * @param result チェック結果 * @param flutterFlg true:Flutter用 false:PC・WEB用 * @param resFormName Flutter用レスポンスForm名 * @return Flutter用String:jsonデータ PC・WEB用 Map<String, Object>:遷移先 */ protected Object returnComm(String url ,Model model,BindingResult result, boolean flutterFlg, String resFormName) { if (flutterFlg) { ResData resData = new ResData(model, result); return resData.getResDataMap(messageSource, resFormName); } else { return url; } } ・・・ protected Object userListUpDwnComm(SrchOrderFForm srchOrderFForm, SrchOrderForm srchOrderForm, BindingResult result, Model model, Pageable pageable, boolean flutterFlg) { //補足:フロント側がFlutter時のsrchOrderFormはsrchOrderFFormを指しています。 if (result.hasErrors()) { model.addAttribute("itemErrorMessages", result.toString()); return returnComm("/members/admin/user/userList", model, result, flutterFlg, "userSrchFForm"); } else { //セッションに載せる this.sessionUserSrchOrderForm.setSrchOrderForm(srchOrderForm); if (this.sessionUserSrchOrderForm.getSrchOrderForm().getSortItemName().equals(srchOrderForm.getSortItemName())) { if (srchOrderForm.getSortOrder().equals("A")) { srchOrderForm.setSortOrder("D"); } else { srchOrderForm.setSortOrder("A"); } } else { srchOrderForm.setSortOrder("A"); } model.addAttribute("srchOrderForm", srchOrderForm); } userListSub(this.sessionUserSrchForm.getUserSrchForm(), this.sessionUserSrchOrderForm.getSrchOrderForm(), model, pageable); if (flutterFlg) { UserSrchFForm userSrchFForm = new UserSrchFForm(); //同一プロパティ(型名まで同じもの)コピー BeanUtils.copyProperties(this.sessionUserSrchForm.getUserSrchForm(), userSrchFForm); BeanUtils.copyProperties(srchOrderFForm, userSrchFForm); Map<String, Object> modelMap = model.asMap(); userSrchFForm.setPage(((Page)modelMap.get("page")).getNumber()); // Flutter向け検索条件+ソート条件+ページ番号 model.addAttribute("userSrchFForm", userSrchFForm); } else { model.addAttribute("userSrchForm", this.sessionUserSrchForm.getUserSrchForm()); } return returnComm("/members/admin/user/userList", model, result, flutterFlg, "userSrchFForm"); }
・スマホ向けController
public class UserFlutterController extends UserCommController { ・・・ /** * ユーザー情報リスト一覧表示処理 * 並び順選択により、ユーザー情報リスト一覧を表示する処理 * * @param srchOrderFForm Flutter向けユーザー情報リスト昇順降順条件+ページ番号 * @param result チェック結果 * @param model モデル * @return jsonデータ */ @SuppressWarnings("unchecked") @PostMapping("/members/admin/user/userA/list_up_dwn") @ResponseBody public Map<String, Object> userListUpDwn(@RequestBody @Validated SrchOrderFForm srchOrderFForm, BindingResult result, Model model) { SrchOrderForm srchOrderForm = (SrchOrderForm)srchOrderFForm; int page = ObjectUtils.isEmpty(srchOrderFForm.getPage())||srchOrderFForm.getPage()==0?0:srchOrderFForm.getPage()-1; Pageable pageable = PageRequest.of(page, pageableDefaultSize, Sort.unsorted()); return (Map<String, Object>)userListUpDwnComm(srchOrderFForm, srchOrderForm, result, model, pageable, true); }
・PC向けController
public class UserPcController extends UserCommController { /** * ユーザー情報リスト一覧表示処理 * テーブル項目リンク押下により、ユーザー情報リスト一覧を表示する処理 * * @param srchOrderForm ユーザー情報リスト昇順降順条件 * @param result チェック結果 * @param mode モード * @param model モデル * @param pageable ページ * @return 遷移先 */ @PostMapping(params="mode=list_up_dwn") public String userListUpDwn(@Validated SrchOrderForm srchOrderForm, BindingResult result, @RequestParam("mode") String mode, Model model, @PageableDefault( size=pageableDefaultSize ) Pageable pageable) { return (String)userListUpDwnComm(null, srchOrderForm, result, model, pageable, false); }