Skip to content

Angular ​

@pollyou/angular ist eine Standalone-Komponente für Angular 17.3 und neuer (getestet mit 17.3, 19 und 22). Sie verpackt das Web-Component <pollyou-survey> aus dem Script-Snippet in eine Angular-API mit Signal-Inputs und Outputs, funktioniert mit Zone.js und zoneless und ist SSR-sicher.

Installation ​

bash
npm install @pollyou/angular
ts
import { Component } from '@angular/core'
import { PollYouSurveyComponent, type PollYouCompleteEvent } from '@pollyou/angular'

@Component({
  selector: 'app-feedback',
  standalone: true,
  imports: [PollYouSurveyComponent],
  template: `
    <pollyou-survey-ng
      surveyId="AbC123xyz0"
      apiBase="https://app.pollyou.org"
      (complete)="danke($event)"
    />
  `,
})
export class FeedbackComponent {
  danke(event: PollYouCompleteEvent) {
    console.log('Antwort gespeichert', event.responseId)
  }
}

AbC123xyz0 ist die öffentliche ID der Umfrage (im Dashboard unter „Teilen“, dort gibt es auch den fertigen Code). Ein CUSTOM_ELEMENTS_SCHEMA ist in Ihrer Anwendung nicht nötig – das regelt die Komponente intern. In Anwendungen mit NgModules wird PollYouSurveyComponent in imports des Moduls eingetragen.

Standardwerte für die ganze App ​

Mit providePollYou() setzen Sie API-Adresse, Sprache und Farbschema einmal zentral. Inputs einzelner Komponenten haben Vorrang.

ts
import { bootstrapApplication } from '@angular/platform-browser'
import { providePollYou } from '@pollyou/angular'

bootstrapApplication(AppComponent, {
  providers: [providePollYou({ apiBase: 'https://app.pollyou.org', locale: 'de' })],
})

Ohne apiBase (weder Input noch Provider) verwendet die Umfrage die Adresse der eigenen Seite – das passt nur, wenn PollYou unter derselben Domain läuft.

Inputs ​

InputTypBedeutung
surveyIdstring (Pflicht)Öffentliche ID der Umfrage.
embedIdstringEmbed-Konfiguration (erlaubte Domains, Vorgaben, signierte Identität).
apiBasestringAdresse der PollYou-API. Standard: providePollYou, sonst die eigene Seite.
mode'inline' | 'popup' | 'slider' | 'fullpage'Darstellung, Standard inline; Overlays sichtbar solange open. Auslöser (Verzögerung, Scrolltiefe …) nur über die Embed-Konfiguration, siehe Overlays.
openbooleanPopup ist geöffnet (nur mode="popup").
localestringSprache, z. B. de. Standard: providePollYou, dann <html lang>, dann der Browser.
theme'auto' | 'light' | 'dark'Farbschema, Standard auto (folgt dem Dark Mode des Systems).
showResultsbooleanfalse blendet Ergebnisse aus, auch wenn die Umfrage sie anzeigen würde.
liveResultsbooleanAngezeigte öffentliche Ergebnisse aktualisieren sich in Echtzeit (Live-Ergebnisse).
identityTokenstringSignierte Identität des angemeldeten Nutzers, siehe unten.
metaRecord<string, string | number | boolean>Zusatzdaten zur Antwort (höchstens 20 Werte zusammen mit hidden).
hiddenRecord<string, string | number | boolean>Versteckte Felder, z. B. { kundennummer: 4711 }.
channelstringKanal in den Statistiken, Standard angular.

Statische Texte schreiben Sie ohne Klammern (surveyId="AbC123xyz0"), alles andere als Property-Binding ([showResults]="false", [hidden]="{ ref: 'newsletter' }").

Outputs ​

Alle Outputs liefern das detail des jeweiligen pollyou:*-Ereignisses (siehe Ereignisse) und laufen innerhalb der Angular-Zone – Änderungen im Handler werden sofort angezeigt.

OutputTypWann
(ready)PollYouReadyEventUmfrage geladen: { surveyId, type, status }
(start)PollYouStartEventErste Antwort gegeben: { surveyId }
(answer)PollYouAnswerEventEine Frage beantwortet: { surveyId, questionKey, answer }
(complete)PollYouCompleteEventAbgeschickt: { surveyId, responseId, results }
(close)PollYouCloseEventPopup geschlossen: { surveyId, mode }
(error)PollYouErrorEventLaden oder Absenden fehlgeschlagen: { surveyId, phase, status }
ts
@Component({
  selector: 'app-umfrage-button',
  standalone: true,
  imports: [PollYouSurveyComponent],
  template: `
    <button type="button" (click)="open = true">Umfrage öffnen</button>
    <pollyou-survey-ng surveyId="AbC123xyz0" mode="popup" [open]="open" (close)="open = false" />
  `,
})
export class UmfrageButtonComponent {
  open = false
}

Setzen Sie open im (close)-Handler zurück, damit ein erneuter Klick das Popup wieder öffnet.

Identitäts-Token ​

Für Umfragen nur für angemeldete Nutzer oder „eine Antwort pro Kunde“ erzeugt Ihr Server ein signiertes Identitäts-Token, das Sie an die Komponente weitergeben:

ts
@Component({
  // …
  template: `
    @if (token(); as token) {
      <pollyou-survey-ng surveyId="AbC123xyz0" [identityToken]="token" />
    }
  `,
})
export class KundenUmfrageComponent {
  token = toSignal(inject(HttpClient).get('/api/pollyou-token', { responseType: 'text' }))
}

Das Embed-Secret bleibt auf dem Server – erzeugen Sie das Token nie im Browser.

Server-Side Rendering (Angular Universal / @angular/ssr) ​

Die Komponente ist SSR-sicher: Auf dem Server wird nur das leere Element <pollyou-survey> mit seinen Attributen gerendert. Das Web-Component (@pollyou/embed-core) wird ausschließlich im Browser per dynamischem import() nach dem ersten Rendern (afterNextRender) geladen und landet in einem eigenen Chunk. Mit Hydration übernimmt der Browser das serverseitig gerenderte Element unverändert; die Umfrage lädt anschließend clientseitig. Es ist keine weitere Konfiguration nötig.

Tests ​

Mit dem Token POLLYOU_LOADER ersetzen Sie das Laden des Web-Components, z. B. in Komponententests:

ts
TestBed.configureTestingModule({
  providers: [{ provide: POLLYOU_LOADER, useValue: () => Promise.resolve() }],
})

Beispiel-App ​

Ein lauffähiges Beispiel liegt im Playground: frontend/apps/playground/angular – Angular-CLI-App mit SSR (outputMode: "server"), Standalone-Komponenten und providePollYou(). / wird pro Anfrage serverseitig gerendert, /about beim Build vorgerendert.

Fehlersuche ​

  • Die Umfrage bleibt leer oder zeigt „nicht gefunden“: Nur veröffentlichte Umfragen sind öffentlich; ein Entwurf oder eine archivierte Umfrage liefert 404. Das Ereignis (error) meldet { phase: 'load', status }.
  • Fehler „blocked by CORS policy“ oder 403 origin_not_allowed: Die Embed-Konfiguration erlaubt nur bestimmte Origins. Tragen Sie die Origin Ihrer Seite ein – mit Schema und Port, also auch den lokalen Dev-Server (z. B. http://localhost:5173). apiBase ist die Origin der API ohne Pfad (https://app.pollyou.org, nicht …/api).
  • Content-Security-Policy: Erlauben Sie die API in connect-src (z. B. connect-src 'self' https://app.pollyou.org, für Live-Ergebnisse zusätzlich den Hub). script-src braucht keinen Eintrag: @pollyou/embed-core ist Teil Ihres Bundles und wird als eigener Chunk von Ihrer Origin nachgeladen. Die Styles setzt das Web-Component per Constructable Stylesheets und CSSOM, 'unsafe-inline' in style-src ist nicht nötig – nur eigenes Theme-CSS wird als <style> eingefügt und fehlt ohne 'unsafe-inline' (die Umfrage funktioniert trotzdem). Das Captcha kommt ohne Worker und eval aus.
  • Lokal in Chrome keine Verbindung zur API: Chrome blockiert mit Local Network Access Anfragen von öffentlichen Seiten an localhost. Die Seite muss selbst lokal laufen (localhost/127.0.0.1), wie die Apps im Playground.
  • SSR: „URL with hostname … is not allowed“: Der SSR-Server von Angular prüft den Host der Anfrage. Tragen Sie Ihre Hosts in angular.json unter build.options.security.allowedHosts ein (der Playground erlaubt 127.0.0.1 und localhost) oder setzen Sie NG_ALLOWED_HOSTS.
  • SSR: leeres Element im HTML: Gewollt – der Server rendert nur <pollyou-survey>, das Web-Component lädt erst im Browser (afterNextRender). Greifen Sie für die Umfrage-ID nicht auf window oder location zu (auf dem Server undefiniert), sondern z. B. auf ActivatedRoute.
  • Hydration-Fehler (NG0500 ff.): Entstehen, wenn Server und Browser unterschiedliche Inputs berechnen. Inputs aus Route oder Server-Daten ableiten, nicht aus Browser-APIs.