LoginSignup
1
0

More than 1 year has passed since last update.

Ionicで簡易コーポレートサイト(アプリ)を作成する #2 -Contact画面編-

Last updated at Posted at 2023-03-13

概要

トップページと同様にお問合せページをIonicで再現します。
Contactコンポーネントを作成し、バリデーションを実装します。

完成イメージ

この時点ではタブがないため、ionic serveでchrome ブラウザから確認できる状態です。

000060.jpg 000050.jpg

Contact画面作成

同様にContactページを作成していきます。

Contactページ

contactページ作成に必要なファイルをコマンドで作成します。
作業フォルダにいることを確認して実行します。

ionic generate page contact

src/にcontactフォルダとファイルが追加されました。

000020.jpg

フォームを作成していきます。
HTMLとIonicコンポーネントを使っていきます。

見た目

contact.page.html

まず見た目だけ作ります。

contact.page.html
<ion-header>
  <ion-toolbar>
    <ion-title>contact</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <div id="container">
    <strong>お問い合わせ</strong>
    <form id="form">
      <p>お名前</p>
      <ion-item lines="full">
        <ion-input type="text" placeholder="お名前"></ion-input>
      </ion-item>
      <span class="error">
        お名前は必須です。
      </span>
      <p>Email</p>
      <ion-item lines="full">
        <ion-input type="email" placeholder="Email"></ion-input>
      </ion-item>
      <span class="error">
        emailは必須かつemailの形式で入力してください。
      </span>
      <p>お問い合わせ内容</p>
      <ion-item>
        <ion-textarea placeholder="お問い合わせ内容"></ion-textarea>
      </ion-item>
      <span class="error">
        お問い合わせ内容は必須かつ1文字以上10文字以下で入力してください。
      </span>
      <ion-button type="submit">送信</ion-button>
    </form>
  </div>
</ion-content>

contact.page.scss

contact.page.scss
ion-content {
    --ion-background-color: white;
}

ion-item {
    --background: rgb(204, 204, 204);
    color: black;
}

ion-input {
    color: black;
}

#container {
    padding-top: 1em;
    padding-left: 3em;
    padding-right: 3em;
    display: flex;
    background-color: white;
    align-items: center;
    justify-content: center;
    flex-direction: column;
}

#container strong {
    color: black;
}

#container p {
    color: black;
    text-align: left;
    width: 100%;
}

#container ion-textarea {
    min-height: 80px;
}

#container ion-button {
    color: black;
    width: 100%;
    --border-radius: 0;
    --background: rgb(204, 204, 204);
    margin-top: 20px;
}

#form {
    width: 100%;
}

.error {
    color: red;
}

確認

タブがないので実機やエミュレータでは遷移ができず問い合わせページがまだ見れないためionic serveで起動してhttp://localhost:8100/contact を確認します。
このような感じになっています。
000030.jpg

機能

まず、フォームをグループとして管理できるようにionicFormという名前をつけます。

contact.page.html
- <form id="form">
+ <form id="form" [formGroup]="ionicForm">

バリデーショーンはReactiveFormsModuleとFormsModuleを使います。
contact.moudle.tsを開いてReactiveFormsModuleを追加します。

contact.module.ts
  import { NgModule } from '@angular/core';
  import { CommonModule } from '@angular/common';
- import { FormsModule } from '@angular/forms';
+ import { FormsModule, ReactiveFormsModule } from '@angular/forms';

  import { IonicModule } from '@ionic/angular';

  import { ContactPageRoutingModule } from './contact-routing.module';

  import { ContactPage } from './contact.page';

  @NgModule({
    imports: [
      CommonModule,
      FormsModule,
      IonicModule,
      ContactPageRoutingModule,
+     ReactiveFormsModule
    ],
    declarations: [ContactPage]
  })
  export class ContactPageModule {}

contact.page.tsを開いてFormGroup, FormBuilder, Validatorsを追加します。

コンポーネントの中でFormBuilderクラスの機能を利用することができようにするため、コンストラクター引数としてFormBuilderクラスのインスタンスを渡します。
ngOnInit()(コンポーネントが初期化されたときに呼び出される)にモジュールを使ってバリデーションを作成します。

contact.page.ts
  import { Component, OnInit } from '@angular/core';
+ import { FormGroup, FormBuilder, Validators } from '@angular/forms';

  @Component({
    selector: 'app-contact',
    templateUrl: './contact.page.html',
    styleUrls: ['./contact.page.scss'],
  })
  export class ContactPage implements OnInit {
+   ionicForm: FormGroup;
-   constructor() { }
+   constructor(public formBuilder: FormBuilder) { }


    ngOnInit() {
+     this.ionicForm = this.formBuilder.group({
+       name: ['', [Validators.required]],
+       email: [
+         '',
+         [
+           Validators.required,
+           Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,3}$'),
+         ],
+       ],
+       content: [
+         '',
+         [
+           Validators.required,
+           Validators.minLength(1),
+           Validators.maxLength(10),
+         ],
+       ],
+     });
    }

  }

コピペ用
this.ionicForm = this.formBuilder.group({
  name: ['', [Validators.required]],
  email: [
    '',
    [
      Validators.required,
      Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,3}$'),
    ],
  ],
  content: [
    '',
    [
      Validators.required,
      Validators.minLength(1),
      Validators.maxLength(10),
    ],
  ],
});

すると、ionicFormの部分でvariableのinitの注意が出ます。tsconfig.jsonを開いて注意を消す設定をします。

tsconfig.json
  "compilerOptions": {
+     "strictPropertyInitialization": false,

htmlに戻ってcontrollerNameを追加していきます。

contact.page.html
  <ion-item lines="full">
-   <ion-input type="text" placeholder="お名前"></ion-input>
+   <ion-input formControlName="name" type="text" placeholder="お名前"></ion-input>
  </ion-item>
  <span class="error">
    お名前は必須です。
  </span>
  <p>Email</p>
  <ion-item lines="full">
-   <ion-input type="email" placeholder="Email"></ion-input>
+   <ion-input formControlName="email" type="email" placeholder="Email"></ion-input>
  </ion-item>
  <span class="error">
    emailは必須かつemailの形式で入力してください。
  </span>
  <p>お問い合わせ内容</p>
  <ion-item>
-   <ion-textarea  placeholder="お問い合わせ内容"></ion-textarea>
+   <ion-textarea formControlName="content" placeholder="お問い合わせ内容"></ion-textarea>
  </ion-item>

Anglurの構文を使ってバリデーションメッセージの表示・非表示を動的にできるようにします。
またformタグにサブミットハンドラーを追加します。

contact.page.html
  <ion-header>
    <ion-toolbar>
      <ion-title>contact</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content>
    <div id="container">
      <strong>お問い合わせ</strong>
-     <form id="form" [formGroup]="ionicForm">
+     <form id="form" [formGroup]="ionicForm" (ngSubmit)="submitForm()">
        <p>お名前</p>
        <ion-item lines="full">
          <ion-input formControlName="name" type="text" placeholder="お名前"></ion-input>
        </ion-item>
-       <span class="error">
+       <span class="error" *ngIf="isSubmitted && errorControl['name'].errors?.['required']">
          お名前は必須です。
        </span>
        <p>Email</p>
        <ion-item lines="full">
          <ion-input formControlName="email" type="email" placeholder="Email"></ion-input>
        </ion-item>
-       <span class="error">
+       <span class="error" *ngIf="isSubmitted && (errorControl['email'].errors?.['required'] ||errorControl['email'].errors?.['pattern'])">
          emailは必須かつemailの形式で入力してください。
        </span>
        <p>お問い合わせ内容</p>
        <ion-item>
          <ion-textarea formControlName="content" placeholder="お問い合わせ内容"></ion-textarea>
        </ion-item>
-       <span class="error">
+       <span class="error" *ngIf="isSubmitted && (errorControl['content'].errors?.['required'] ||errorControl['content'].errors?.['min'] ||errorControl['content'].errors?.['max']  )">
          お問い合わせ内容は必須かつ1文字以上10文字以下で入力してください。
        </span>
        <ion-button type="submit">送信</ion-button>
      </form>
    </div>
  </ion-content>

コピペ用
    <form id="form" [formGroup]="ionicForm" (ngSubmit)="submitForm()">
      <p>お名前</p>
      <ion-item lines="full">
        <ion-input formControlName="name" type="text" placeholder="お名前"></ion-input>
      </ion-item>
      <span class="error" *ngIf="isSubmitted && errorControl['name'].errors?.['required']">
        お名前は必須です。
      </span>
      <p>Email</p>
      <ion-item lines="full">
        <ion-input formControlName="email" type="email" placeholder="Email"></ion-input>
      </ion-item>
      <span class="error"
        *ngIf="isSubmitted && (errorControl['email'].errors?.['required'] ||errorControl['email'].errors?.['pattern'])">
        emailは必須かつemailの形式で入力してください。
      </span>
      <p>お問い合わせ内容</p>
      <ion-item>
        <ion-textarea formControlName="content" placeholder="お問い合わせ内容"></ion-textarea>
      </ion-item>
      <span class="error" *ngIf="isSubmitted && (errorControl['content'].errors?.['required'] ||errorControl['content'].errors?.['min'] ||errorControl['content'].errors?.['max']  )">文字以下で入力してください。
      </span>
      <ion-button type="submit">送信</ion-button>
    </form>

SubmitForm()を作成し、制御していきます。
一旦、バリデーションがすべてスルーだったらコンソールに値が表示されるようにします。
またget errorControl()を使って、Angulerの特定のフォームコントロールエラーメッセージを返します。
isSubmittedは初期値はfalseにし、送信が押されたら、trueとなるようにしています。

contact.page.ts
  import { Component, OnInit } from '@angular/core';
  import { FormGroup, FormBuilder, Validators } from '@angular/forms';

  @Component({
    selector: 'app-contact',
    templateUrl: './contact.page.html',
    styleUrls: ['./contact.page.scss'],
  })
  export class ContactPage implements OnInit {
+   isSubmitted = false;
    ionicForm: FormGroup;

    constructor(public formBuilder: FormBuilder) { }


    ngOnInit() {
      this.ionicForm = this.formBuilder.group({
        name: ['', [Validators.required]],
        email: [
          '',
          [
            Validators.required,
            Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,3}$'),
          ],
        ],
        content: [
          '',
          [
            Validators.required,
            Validators.minLength(1),
            Validators.maxLength(10),
          ],
        ],
      });
    }

+   submitForm() {
+     this.isSubmitted = true;
+     if (!this.ionicForm.valid) {
+       return;
+     }
+     let data = this.ionicForm.value;
+     console.log(data);
+   }

+   get errorControl() {
+     return this.ionicForm.controls;
+   }
  }

コピペ用
submitForm() {
    this.isSubmitted = true;
    if (!this.ionicForm.valid) {
      return;
    }
    let data = this.ionicForm.value;
    console.log(data);
  }

  get errorControl() {
    return this.ionicForm.controls;
  }

ionic serveで確認し、バリデーションが想定どおり動いていて、
000050.jpg
適切な値が入った状態でボタンクリックするとコンソールに値が表示されていることを確認します。
000040.jpg

API連携

console.log(data)を削除してAPI連携のコードを追加します。

contact.page.ts
   submitForm() {
      this.isSubmitted = true;
      if (!this.ionicForm.valid) {
        return;
      }
      let data = this.ionicForm.value;
+     const api_url = 'apiのURL';
+     fetch(api_url, {
+       method: 'post',
+       headers: {
+         'Content-Type': 'application/x-www-form-urlencoded',
+       },
+       body: encodeURI(
+         `name=${data.name}&email=${data.email}&body=${data.body}`
+       ),
+     })
+       .then((response) => response.json())
+       .then((result) => alert(result.message))
+       .catch((error) => alert(error.message));
    }
コピペ用
const api_url = 'apiのURL';
fetch(api_url, {
 method: 'post',
 headers: {
   'Content-Type': 'application/x-www-form-urlencoded',
 },
 body: encodeURI(
   `name=${data.name}&email=${data.email}&body=${data.body}`
 ),
})
 .then((response) => response.json())
 .then((result) => alert(result.message))
 .catch((error) => alert(error.message));

確認

きちんとmessageが返ってきています。
000060.jpg

関連コンテンツ

1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0