「[[.NET 開発基盤部会 Wiki>http://dotnetdevelopmentinfrastructure.osscons.jp]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。
-[[戻る>Flutter]]
--[[Flutterのファースト・ステップ]]
--[[Flutterのセカンド・ステップ]]
--[[Flutterのサード・ステップ]]
--Flutterの4thステップ
--[[Flutterの5thステップ]]
*目次 [#q3193e80]
#contents
*概要 [#d0e5c30b]
[[Flutter]] の step by step(其の四)。
*手順1:業務ぃーな、CRUDを実装してみる。 [#d0496641]
**入力フォームの作成 [#kafe8fef]
-公式のサンプルに問題があるらしい。
-取り敢えず、基本のTextFormFieldを使ってみる。
***前編 [#dc5979d3]
-ファースト・ステップ~
以下のような感じ。
// main.dart
Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'id'),
),
TextFormField(
decoration: InputDecoration(labelText: 'password'),
obscureText: true, // 追加
),
],
),
)
-セカンド・ステップ~
以降、[[技術は熱いうちに打て>#o3109b1b]]が参考になる。
--doneボタンが押された時の処理を記述
--doneからnextに変更しフォーカス移動
--初期値設定と現状値の保存
--インライン・バリデーション処理の実装
-ポイント
--その1: 意味もなくsave()するな。~
単に、子要素のonSave()を呼ぶ処理なので。
--その2: 意味もなくステートを持つな。~
FormにGlobalKey<FormState>張って、~
GlobalKey<FormState>.currentState?.save()で上記のonSave()が動作。
--その3: やたらめったらFormを書き換えるな。~
要するに、setStateを書かなくてもイイというコトらしい。
--その4: 初期値を入れるのにTextEditingControllerを使うな。~
TextFormField.initialValueを使用する。
--その5: AutofillHintsちゃんと書こう。~
HTML.Inputタグで言うところのautocomplete属性。
***後編 [#a826eb3e]
-サード・ステップ
--現状値の保存に対して、現状値の設定は?~
FormFieldStateにGlobalKey<FormFieldState>張って、~
GlobalKey<FormFieldState>.currentState?.didChange(this._XXXX)。
--ドロップダウンリスト~
[[DropdownButton>Flutterのファースト・ステップ#mbd05014]]を使用する。
--バリデーション処理が長い。
---implements Validatableで部品化が可能。
---[[カスタム・コントロール>#gd4970e7]]的なコトも可能。
**一覧表示の作成 [#j6f8b2ea]
***[[WebAPIでデータを取得する。>Flutterのファースト・ステップ#k0b7d0c5]] [#sb8e48be]
***JSONをdecodeする。 [#le6af3e5]
decodeするdart:convertライブラリのサンプルが複数ある。
-JSON.decodeは古いライブラリ。
-今は、jsonDecodeのライブラリを使用する。
-以下の何れかの方に変換される模様。
--Map<String, dynamic>
--List<dynamic>
>DBの一覧ならList<dynamic>になる。
***DataTableを使用した一覧 [#vc52168b]
-業務系では、DataTableのWidgetが使えそう。
-Bindingは、DataTableの、
--columns: で、列定義を行い、
--rows: で、DataRow / DataCellのlistを返す。
***ListViewを使用した一覧 [#m8020487]
-ListView.builderのitemBuilderでcardデザインを返す。
-cardデザインは[[プッシュ通知>Flutterのサード・ステップ#p7b4ca10]]のサンプル中に含まれる。
***, etc. [#oc5559f6]
**参考 [#o3109b1b]
-【誰でも分かる!】FlutterのFormを一から~
作りながら解説してみたよ | 技術は熱いうちに打て!~
https://blog.dalt.me/2036
-[Flutter]入力フォームのインラインバリデーションを実装する | DevelopersIO~
https://dev.classmethod.jp/articles/flutter-inline-validation/
-dart - How to add dynamically items to the table in flutter? - Stack Overflow~
https://stackoverflow.com/questions/53997496/how-to-add-dynamically-items-to-the-table-in-flutter
***Qiita [#t26ef242]
-Flutter Form系Widgetの使い方 〜 すべてのWidgetを学習~
https://qiita.com/kurun_pan/items/3378875ff034614f381a
-お前らのFormのサンプルコードはすべて間違っている~
https://qiita.com/hummer/items/8f1ba5ae09d31f42a465
-【初心者】Flutter:APIでデータ取得して、一覧表示させるサンプルアプリ~
https://qiita.com/yasutaka_ono/items/6d2a0d3b0856598f9788
*手順2:気になっている所を修正する。 [#q42ac453]
**画面遷移処理 [#m3ff833d]
-画面内の遷移と[[Drawerの遷移>Flutterのファースト・ステップ#a39c49ff]]がゴッチャになる。
-調べていくと、最初に表示された画面は、~
ルートなので、ソレ以上、POPできないらしい。
-以下の修正を加えると、ソレっぽくなる。
***画面内の遷移は、[[スタックにプッシュする。>Flutterのファースト・ステップ#ve163562]] [#c2806f2e]
故に、戻る処理は、
-基本的に、戻るボタンで前画面に戻る。
-処理次第でpopを明示的に実装する。
***[[Drawerの遷移>Flutterのファースト・ステップ#a39c49ff]]は、一度スタックを空にする。 [#je4c8223]
以下のように実装する。
-ルートへの遷移~
ルートまでpopする。
onTap: () {
while(Navigator.of(context).canPop()){
Navigator.of(context).pop();
}
},
-ルート以外への遷移~
ルートまでpopした後、1つダケpushする。
onTap: () {
while(Navigator.of(context).canPop()){
Navigator.of(context).pop();
}
Navigator.of(context).pushNamed("/appauth");
},
**Widgetの部品化 [#p264249e]
-[[全体構成の見直し>Flutterのサード・ステップ#dd29a972]] の [[common>Flutterのサード・ステップ#u6459cfd]]に入れる。
-StatelessWidgetでラップする方法と、~
Widgetをextendsする方法がある模様。
--前者は、簡単な特化型のカスタマイズ
--後者は、高難易度の汎化型のカスタマイズ
-C#的に言うと、
--StatelessWidgetでラップする方法~
ユーザ・コントロール的にラップするか?
--Widgetをextendsする方法~
[[カスタム・コントロール>https://techinfoofmicrosofttech.osscons.jp/index.php?.NET%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA%E6%96%B9%E6%B3%95]]化するか?
>みたいな。
-Windows Formsのようなオナー・ドローは不要。~
WPFのように子要素で実装可能(Widget buildメソッドで返す)。
***Drawer [#b5f0071c]
-StatelessWidgetでラップする方法
--定義して
import 'package:flutter/material.dart';
class MyDrawer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Drawer(
--使用する。
return Scaffold(
...,
drawer: MyDrawer(),
);
***Button [#ee2d48f4]
-StatelessWidgetでラップする方法
--定義して
import 'package:flutter/material.dart';
class MyElevatedButton extends StatelessWidget {
final String _caption;
final VoidCallback _onPressed;
const MyElevatedButton(
this._caption, this._onPressed,
{Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(
child: Text(this._caption),
...,
),
onPressed: this._onPressed,
);
}
}
--使用する。
MyElevatedButton('EnglishWords Button', this._englishWords),
***FormField [#gd4970e7]
-対象のWidgetをextends する方法
--定義して
class CounterFormField extends FormField<int> {
CounterFormField({
FormFieldSetter<int> onSaved,
FormFieldValidator<int> validator,
int initialValue = 0,
bool autovalidate = false
}) : super(
onSaved: onSaved,
validator: validator,
initialValue: initialValue,
autovalidate: autovalidate,
builder: (FormFieldState<int> state) {
return Row(
この中で、state.valueとかstate.didChangeが使える。
);
}
);
}
--使用する。
CounterFormField(
autovalidate: false,
validator: (value) {
...
},
onSaved: (value) => this._value = value,
)
***, etc. [#v5e6a9fc]
**その他の共通化 [#r91b2e7d]
[[全体構成の見直し>Flutterのサード・ステップ#dd29a972]] の 各フォルダに入れる。
***変数/定数クラス [#haae6266]
→ [[configs>Flutterのサード・ステップ#vc2278c4]]
***関数クラス [#e46b7b58]
→ [[helpers>Flutterのサード・ステップ#u4ee8972]]
***サービス・クラス [#wd1132bc]
→ [[services>Flutterのサード・ステップ#o8aca8f8]]
**参考 [#xea15178]
-dart - Persisting AppBar Drawer across all Pages Flutter~
https://stackoverflow.com/questions/51659805/persisting-appbar-drawer-across-all-pages-flutter
-ボタンを「コンポーネント化」しよう|Flutter ボタン自作入門~
https://zenn.dev/heavenosk/books/flutter-button-diy/viewer/extracting_button
-Creating Custom Form Fields in Flutter~
by AbdulRahman AlHamali | SAUGO 360 | Medium~
https://medium.com/saugo360/creating-custom-form-fields-in-flutter-85a8f46c2f41
*[[参考>Flutter#a9ed99c8]] [#b96b3900]