Home / Hướng dẫn / Tích hợp biểu mẫu liên hệ góc (Độc lập & Tín hiệu)
HƯỚNG DẪN TÍCH HỢP · ANGULAR & SPA

Tích hợp biểu mẫu liên hệ góc (Độc lập & Tín hiệu)

Kết nối các ứng dụng Angular 17/18+ với Lugatu bằng cách sử dụng Thành phần độc lập, Tín hiệu phản ứng và HttpClient để phân phối biểu mẫu liên hệ đáng tin cậy mà không cần duy trì máy chủ SMTP.

1. Thành phần biểu mẫu liên hệ độc lập với tín hiệu phản ứng

Angular hiện đại ưu tiên các Thành phần và Tín hiệu độc lập hơn NgModules nặng. Việc triển khai này cung cấp một biểu mẫu liên hệ có thể truy cập được với các trạng thái tải phản ứng, lỗi và thành công gửi trực tiếp đến 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 & Chuyển tiếp từ máy chủ đến máy chủ phổ biến góc

Nếu ứng dụng Angular của bạn chạy với Angular SSR (công cụ Node / Express), bạn có thể ủy quyền các yêu cầu thông qua trình xử lý tuyến phía máy chủ để bảo vệ khóa API Lugatu Server-to-Server của mình.

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. Cấu hình Bot Defense & Honeypot

Lugatu tự động kiểm tra trường _gotcha. Giữ nó ở chế độ ẩn đối với khách truy cập bằng cách sử dụng display:none và tabindex="-1". Các spam lấp đầy mọi thông tin đầu vào DOM sẽ kích hoạt chế độ im lặng.

tip

Không bao giờ sử dụng nhãn biểu mẫu cho đầu vào honeypot. Tắt tính năng tự động hoàn thành và loại trừ trường khỏi các tên có thể truy cập được bằng trình đọc màn hình.

Bảo mật & xác thực bất biến

Bất biến bảo mật: Không bao giờ được nhóm các khóa API từ máy chủ đến máy chủ (lug_live_...) vào các tệp nội dung Angular hoặc môi trường.ts phía máy khách. Sử dụng điểm cuối công khai để gửi trực tiếp từ máy khách hoặc chuyển tiếp qua điểm cuối của máy chủ.

Khắc phục sự cố và các lỗi nhập thường gặp

HTTP 403 FORBIDDEN_BROWSER_ORIGIN khi gửi từ Angular

Điểm cuối của biểu mẫu công khai cho phép gửi nhiều nguồn gốc từ bất kỳ trình duyệt nào. Nếu bạn đang gọi điểm cuối từ máy chủ đến máy chủ (POST /api/v1/forms/{id}/submissions) trực tiếp từ Angular, hãy chuyển sang điểm cuối công khai (POST /api/v1/public/forms/{id}/submissions) hoặc chuyển tiếp thông qua chương trình phụ trợ.

Câu hỏi thường gặp

Lugatu có hỗ trợ Angular SSR với quá trình hydrat hóa ứng dụng khách không?

Đúng. Việc gửi biểu mẫu công khai Lugatu được thực hiện thông qua tìm nạp phía máy khách hoặc HttpClient sau khi người dùng tương tác, điều này hoàn toàn tương thích với Angular SSR và quá trình hydrat hóa máy khách.

Bạn đã sẵn sàng tạo điểm cuối biểu mẫu chưa?

Bắt đầu miễn phí trong vài giây. Không cần thẻ tín dụng.

Bắt đầu miễn phí →