[僕のlonicでスマホアプリ開発]#6 データインポート/エクスポート画面作成

# はじめに
前回の[[僕のlonicでスマホアプリ開発]#5 残高確認画面作](https://qiita.com/SSKNOK/items/da2fe78487d496841b07)続きになります。
今回作成するスマホアプリは画面が以下の通りになる想定ですが、
- 残高確認画面
- 残高登録画面
- 口座登録画面
- データインポート/エクスポート画面

今回はデータインポート/エクスポート画面を実装します。

# ソース全量

本当にコマッタポイントがないので、ソース全量を

```vue:src/views/ImportExport.vue
<template>
  <ion-page>
    <ion-header>
      <ion-toolbar>
        <ion-title>IMPORT/EXPORT</ion-title>
      </ion-toolbar>
    </ion-header>
    <ion-content :fullscreen="true">
      <ion-header collapse="condense">
        <ion-toolbar>
          <ion-title size="large">IMPORT/EXPORT</ion-title>
        </ion-toolbar>
      </ion-header>
      <p class="how-to-use">
        If you want to import data from other devices, input data exported other
        devices into textarea.
      </p>
      <p class="how-to-use">
        If you want to export data to other devices, push "EXPORT" button and
        paste shown text to other devices.
      </p>
      <ion-grid>
        <ion-row>
          <!-- IMPORTボタン -->
          <ion-col>
            <ion-button expand="block" color="success" @click="registAllInfo"
              ><ion-icon :icon="arrowDownOutline" slot="start"></ion-icon
              >IMPORT</ion-button
            >
          </ion-col>
          <!-- EXPORTボタン -->
          <ion-col>
            <ion-button expand="block" color="warning" @click="getAllInfo"
              ><ion-icon :icon="arrowUpOutline" slot="start"></ion-icon
              >EXPORT</ion-button
            >
          </ion-col>
        </ion-row>
      </ion-grid>
      <ion-item>
        <ion-textarea
          auto-grow="true"
          placeholder="input or output data"
          :value="data"
          @input="data = $event.target.value"
        ></ion-textarea>
      </ion-item>
    </ion-content>
  </ion-page>
</template>

<script setup>
import {
  IonPage,
  IonHeader,
  IonToolbar,
  IonTitle,
  IonContent,
  IonGrid,
  IonRow,
  IonCol,
  IonIcon,
  IonButton,
  IonItem,
  IonTextarea,
  onIonViewWillEnter,
  alertController,
} from "@ionic/vue";
import { arrowDownOutline, arrowUpOutline } from "ionicons/icons";
import ExploreContainer from "@/components/ExploreContainer.vue";
import { ref } from "vue";
import { Storage } from "@ionic/storage";

/* ******** プロパティ ******** */
let data = ref();

let storage;

const SPLIT_MARK = "{SPLIT}"; // データの区切りマーク

/* ******** ライフサイクルフック ******** */
onIonViewWillEnter(async function () {
  // ストレージ準備
  const store = new Storage();
  storage = await store.create();

  // テキストエリアクリア
  data.value = "";
});

/* ******** メソッド ******** */
/* ----------------------------------
method:移行データ出力。
detail:移行用に残高情報および口座情報をストレージから取得し、テキストエリアに表示する。
 ---------------------------------- */
const getAllInfo = async function () {
  // エクスポートJSON格納リスト
  let exportJsonJointStr = "";

  await storage.forEach((value, key) => {
    let infoJson = JSON.parse(value);
    let exportJson = JSON.stringify({
      key: key,
      value: infoJson,
    });
    exportJsonJointStr = exportJsonJointStr.concat(SPLIT_MARK, exportJson);
    data.value = exportJsonJointStr;
  });
};

/* ----------------------------------
method:移行データ入力。
detail:移行用の残高情報および口座情報をストレージに格納する。
 ---------------------------------- */
const registAllInfo = async function () {
  if (checkEmptyValue(data.value)) {
    return;
  }

  let registInfoList = data.value.split(SPLIT_MARK);
  // 無駄な最初の要素を削除
  registInfoList.shift();
  // ストレージをクリア
  storage.clear();
  // 各要素をストレージに格納する
  registInfoList.forEach(async (infoJsonStr) => {
    let infoJson = JSON.parse(infoJsonStr);
    await storage.set(infoJson.key, JSON.stringify(infoJson.value));
  });
  presentAlert();
};

/* ----------------------------------
method:データ入力完了用アラート表示。
detail:データ入力完了を示すアラートを表示する。
 ---------------------------------- */
const presentAlert = async () => {
  const alert = await alertController.create({
    header: "INFOMATION",
    subHeader: "Importing data is finished!",
    buttons: ["OK"],
  });

  await alert.present();
};

/* ----------------------------------
method:空文字・NULL・undefined判定
detail:空文字・NULL・undefinedの場合、trueを返す。
 ---------------------------------- */
const checkEmptyValue = function (targetValue) {
  if (targetValue === null || targetValue === "" || targetValue === undefined) {
    return true;
  }
  return false;
};
</script>

<style scoped>
.how-to-use {
  padding-right: 20px;
  padding-left: 20px;
}
</style>
```

次回は最後の壁
`残高グラフ画面`を実装していきます。