Home / Guías / Integración de formulario de contacto angular (independiente y señales)
GUÍA DE INTEGRACIÓN · ANGULAR & SPA

Integración de formulario de contacto angular (independiente y señales)

Conecte aplicaciones Angular 17/18+ a Lugatu utilizando componentes independientes, señales reactivas y HttpClient para una entrega confiable de formularios de contacto sin mantener un servidor SMTP.

1. Componente de formulario de contacto independiente con señales reactivas

Modern Angular prefiere los componentes y señales independientes a los NgModules pesados. Esta implementación proporciona un formulario de contacto accesible con estados de carga reactiva, error y éxito que se envían directamente a 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 y reenvío universal de servidor a servidor angular

Si su aplicación Angular se ejecuta con Angular SSR (motor Node/Express), puede enviar consultas a través de un controlador de ruta del lado del servidor para proteger su clave API de servidor a servidor de Lugatu.

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. Configuración de Bot Defense y Honeypot

Lugatu inspecciona el campo _gotcha automáticamente. Manténgalo invisible para los visitantes humanos usando display:none y tabindex="-1". Los spambots que llenan cada entrada DOM desencadenan una supresión silenciosa.

tip

Nunca utilice etiquetas de formulario para entradas de honeypot. Deje desactivado el autocompletado y excluya el campo de los nombres accesibles para lectores de pantalla.

Invariante de seguridad y autenticación

Invariante de seguridad: las claves API de servidor a servidor (lug_live_...) nunca deben incluirse en activos Angular del lado del cliente o en archivos Environment.ts. Utilice el punto final público para envíos directos del cliente o reenvío a través de puntos finales del servidor.

Solución de problemas y errores comunes de ingesta

HTTP 403 FORBIDDEN_BROWSER_ORIGIN al enviar desde Angular

Los puntos finales de formularios públicos permiten envíos de orígenes cruzados desde cualquier navegador. Si llama al punto final de servidor a servidor (POST /api/v1/forms/{id}/submissions) directamente desde Angular, cambie al punto final público (POST /api/v1/public/forms/{id}/submissions) o reenvíe a través de un backend.

Preguntas frecuentes

¿Lugatu admite Angular SSR con la hidratación del cliente?

Sí. Los envíos de formularios públicos de Lugatu se realizan mediante la recuperación del lado del cliente o HttpClient después de la interacción del usuario, que es completamente compatible con Angular SSR y la hidratación del cliente.

¿Listo para crear el punto final de su formulario?

Comience gratis en segundos. No se requiere tarjeta de crédito.

Comience gratis →