Home / ガイド / Angular コンタクト フォームの統合 (スタンドアロンおよびシグナル)
統合ガイド · ANGULAR & SPA

Angular コンタクト フォームの統合 (スタンドアロンおよびシグナル)

SMTP サーバーを維持することなく、スタンドアロン コンポーネント、リアクティブ シグナル、および HttpClient を使用して Angular 17/18+ アプリケーションを Lugatu に接続し、信頼性の高いコンタクト フォーム配信を実現します。

1. リアクティブ信号を備えたスタンドアロンのコンタクトフォームコンポーネント

最新の Angular は、重い NgModule よりもスタンドアロン コンポーネントとシグナルを優先します。 この実装では、Lugatu に直接送信されるリアクティブな読み込み、エラー、成功の状態を備えたアクセス可能な問い合わせフォームが提供されます。

contact-form.component.ts typescript
import { Component, signal, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-contact-form',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <form (ngSubmit)="onSubmit()" class="space-y-4 max-w-md">
      <div>
        <label for="name" class="block text-sm font-semibold mb-1">Your Name</label>
        <input id="name" type="text" [(ngModel)]="name" name="name" required class="w-full border rounded-xl p-2.5" />
      </div>
      <div>
        <label for="email" class="block text-sm font-semibold mb-1">Email Address</label>
        <input id="email" type="email" [(ngModel)]="email" name="email" required class="w-full border rounded-xl p-2.5" />
      </div>
      <div>
        <label for="message" class="block text-sm font-semibold mb-1">Message</label>
        <textarea id="message" rows="4" [(ngModel)]="message" name="message" required class="w-full border rounded-xl p-2.5"></textarea>
      </div>

      <!-- Honeypot spam defense -->
      <input type="text" [(ngModel)]="gotcha" name="_gotcha" style="display:none !important" tabindex="-1" autocomplete="off" />

      <button type="submit" [disabled]="isSubmitting()" class="btn-primary-editorial py-2.5 px-6">
        {{ isSubmitting() ? 'Sending...' : 'Send Message' }}
      </button>

      <p *ngIf="isSuccess()" class="text-sm text-green-700 font-medium">Thank you! Your message has been received.</p>
      <p *ngIf="errorMessage()" class="text-sm text-red-600">{{ errorMessage() }}</p>
    </form>
  `,
})
export class ContactFormComponent {
  private http = inject(HttpClient);

  name = signal('');
  email = signal('');
  message = signal('');
  gotcha = signal('');

  isSubmitting = signal(false);
  isSuccess = signal(false);
  errorMessage = signal('');

  onSubmit() {
    if (this.gotcha()) return; // Silent discard for automated bot submissions

    this.isSubmitting.set(true);
    this.errorMessage.set('');

    const payload = {
      fields: {
        name: this.name(),
        email: this.email(),
        message: this.message(),
      },
      honeypot: this.gotcha(),
    };

    this.http.post('https://www.lugatu.com/api/v1/public/forms/YOUR_PUBLIC_FORM_ID/submissions', payload)
      .subscribe({
        next: () => {
          this.isSubmitting.set(false);
          this.isSuccess.set(true);
          this.name.set('');
          this.email.set('');
          this.message.set('');
        },
        error: () => {
          this.isSubmitting.set(false);
          this.errorMessage.set('Submission failed. Please try again.');
        },
      });
  }
}

2. SSR および Angular ユニバーサル サーバー間転送

Angular アプリケーションが Angular SSR (ノード / Express エンジン) で実行されている場合、サーバー側のルート ハンドラーを通じて問い合わせをプロキシして、Lugatu サーバー間 API キーを保護できます。

server.ts typescript
// Express / Node backend endpoint in Angular SSR
server.post('/api/contact', async (req, res) => {
  const { name, email, message, _gotcha } = req.body;
  if (_gotcha) return res.status(200).json({ ok: true });

  try {
    const response = await fetch(`https://www.lugatu.com/api/v1/forms/${process.env.LUGATU_FORM_ID}/submissions`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.LUGATU_API_KEY}`,
        'Content-Type': 'application/json',
        'Idempotency-Key': crypto.randomUUID(),
      },
      body: JSON.stringify({ fields: { name, email, message } }),
    });

    res.status(response.status).json({ ok: response.ok });
  } catch (error) {
    res.status(500).json({ error: 'Failed to deliver message' });
  }
});

3. ボット防御とハニーポットの構成

Lugatu は _gotcha フィールドを自動的に検査します。 display:none と tabindex="-1" を使用して、人間の訪問者には見えないようにしてください。 すべての DOM 入力を満たすスパムボットは、サイレント抑制をトリガーします。

tip

ハニーポット入力にはフォーム ラベルを決して使用しないでください。 オートコンプリートをオフのままにして、スクリーン リーダーがアクセスできる名前からフィールドを除外します。

セキュリティと認証の不変性

セキュリティの不変条件: サーバー間の API キー (lug_live_...) は、クライアント側の Angular アセットまたはenvironment.ts ファイルに決してバンドルしてはなりません。 クライアントから直接送信するか、サーバー エンドポイント経由で転送するには、パブリック エンドポイントを使用します。

トラブルシューティングと一般的な取り込みエラー

Angular から送信する場合の HTTP 403 FORBIDDEN_BROWSER_ORIGIN

パブリック フォーム エンドポイントでは、任意のブラウザからのクロスオリジン送信が許可されます。 Angular からサーバー間エンドポイント (POST /api/v1/forms/{id}/submissions) を直接呼び出している場合は、パブリック エンドポイント (POST /api/v1/public/forms/{id}/submissions) に切り替えるか、バックエンド経由で転送します。

よくある質問

Lugatu はクライアント ハイドレーションを備えた Angular SSR をサポートしていますか?

はい。 Lugatu パブリック フォームの送信は、ユーザー操作後にクライアント側のフェッチまたは HttpClient を介して実行されます。これは、Angular SSR およびクライアント ハイドレーションと完全に互換性があります。

フォームエンドポイントを作成する準備はできましたか?

数秒で無料で始められます。 クレジットカードは必要ありません。

無料で始める →