Skip to content

Commit

Permalink
feat(NOJIRA-123): Add onStarted callback for "submission start" eve…
Browse files Browse the repository at this point in the history
…nt (#627)
  • Loading branch information
Matej Lednicky authored Nov 23, 2023
1 parent 308715e commit e44b5e7
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 2 deletions.
31 changes: 31 additions & 0 deletions docs/callbacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ You can listen to various events as the respondent is filling out the typeform o
Available callbacks:

- **onReady** fires when the form is loaded
- **onStarted** fires on the form "submission start" event
- **onSubmit** fires when user submits the form
- **onClose** fires when user closes the modal window
- **onQuestionChanged** fires when user navigates between form questions
Expand Down Expand Up @@ -50,6 +51,36 @@ Or in HTML:
</script>
```

## onStarted

The `onStarted` callback will execute when the embedded typeform "submission start" even is trigerred.

In JavaScript:

```javascript
import { createWidget } from '@typeform/embed'
import '@typeform/embed/build/css/widget.css'

createWidget('<form-id>', {
onStarted: ({ formId, responseId }) => {
console.log(`Form ${formId} started with response ID ${responseId}`)
},
})
```

Or in HTML:

```html
<div data-tf-widget="<form-id>" data-tf-on-started="started"></div>
<script src="//embed.typeform.com/next/embed.js"></script>
<script>
// this function needs to be available on global scope (window)
function started({ formId }) {
console.log(`Form ${formId} started with response ID ${responseId}`)
}
</script>
```

## onSubmit

The `onSubmit` callback will execute immediately after a respondent successfully submits the typeform by clicking the "Submit" button.
Expand Down
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ If you embed via HTML, you need to pass optinos as attributes with `data-tf-` pr
| notificationDays | number | display red notification dot, hide for given number of days since popover is open (popover only) | `undefined` |
| autoClose | number / boolean | time (ms) until the embedded typeform will automatically close after a respondent clicks the Submit button. (all embeds except widget) | `undefined` |
| onReady | function | fires when the form is loaded | `undefined` |
| onStarted | function | fires on the "submission start" event, contains `responseId` in the payload | `undefined` |
| onSubmit | function | fires when user submits the form | `undefined` |
| onClose | function | fires when the form is closed (when opened in modal window) | `undefined` |
| onQuestionChanged | function | fires when user navigates between form questions | `undefined` |
Expand Down
9 changes: 7 additions & 2 deletions packages/demo-html/public/callbacks.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
data-tf-widget="HLjqXS5W"
data-tf-source="localhost"
data-tf-on-ready="onTypeformReady"
data-tf-on-started="onTypeformStarted"
data-tf-on-submit="onTypeformSubmit"
data-tf-on-question-changed="onTypeformQuestionChanged"
data-tf-on-height-changed="onTypeformHeightChanged"
Expand All @@ -28,6 +29,7 @@
data-tf-popup="HLjqXS5W"
data-tf-source="localhost"
data-tf-on-ready="onTypeformReady"
data-tf-on-started="onTypeformStarted"
data-tf-on-submit="onTypeformSubmit"
data-tf-on-question-changed="onTypeformQuestionChanged"
data-tf-on-close="onTypeformClose"
Expand All @@ -45,18 +47,21 @@
console.log('form ready', data)
}

function onTypeformStarted(data) {
alert('onStarted')
console.log('form started', data)
}

function onTypeformSubmit(data) {
alert('onSubmit')
console.log('form submitted', data)
}

function onTypeformQuestionChanged(data) {
alert(`onQuestionChanged: ${data.ref}`)
console.log('form question changed', data)
}

function onTypeformHeightChanged(data) {
alert(`onHeightChanged: ${data.height}px`)
console.log('form height changed', data)
}

Expand Down
7 changes: 7 additions & 0 deletions packages/embed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ Closing and opening a typeform in modal window will restart the progress from th
| [notificationDays](https://codesandbox.io/s/github/Typeform/embed-demo/tree/main/demo-html/popover-html) | number | display red notification dot, hide for given number of days since popover is open (popover only) | `undefined` |
| [autoClose](https://codesandbox.io/s/github/Typeform/embed-demo/tree/main/demo-html/autoclose) | number / boolean | time (ms) until the embedded typeform will automatically close after a respondent clicks the Submit button. (all embeds except widget) | `undefined` |
| [onReady](https://codesandbox.io/s/github/Typeform/embed-demo/tree/main/demo-html/callbacks) | function | fires when the form is loaded | `undefined` |
| [onStarted](https://codesandbox.io/s/github/Typeform/embed-demo/tree/main/demo-html/callbacks) | function | fires on the "submission start" event, contains `responseId` in the payload | `undefined` |
| [onSubmit](https://codesandbox.io/s/github/Typeform/embed-demo/tree/main/demo-html/callbacks) | function | fires when user submits the form | `undefined` |
| [onClose](https://codesandbox.io/s/github/Typeform/embed-demo/tree/main/demo-html/callbacks) | function | fires when the form is closed (when opened in modal window) | `undefined` |
| [onQuestionChanged](https://codesandbox.io/s/github/Typeform/embed-demo/tree/main/demo-html/callbacks) | function | fires when user navigates between form questions | `undefined` |
Expand Down Expand Up @@ -228,6 +229,9 @@ You can listen to form events by providing callback methods:
onReady: ({ formId }) => {
console.log(`Form ${formId} is ready`)
},
onStarted: ({ formId, responseId }) => {
console.log(`Form ${formId} started with response ID ${responseId}`)
},
onQuestionChanged: ({ formId, ref }) => {
console.log(`Question in form ${formId} changed to ${ref}`)
},
Expand Down Expand Up @@ -259,6 +263,9 @@ Callback method receive payload object from the form. Each payload contains form

- onReady
- `formId` (string)
- onStarted
- `formId` (string)
- `responseId` (string)
- onQuestionChanged
- `formId` (string)
- `ref` (string) identifies currently displayed question
Expand Down
4 changes: 4 additions & 0 deletions packages/embed/src/base/actionable-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export type ActionableOptions = {
* Callback function that will be executed once the typeform is ready.
*/
onReady?: (event: WithFormId) => void
/**
* Callback function that will be executed once the typeform "submission start" event is fired.
*/
onStarted?: (event: WithFormId & WithResponseId) => void
/**
* Callback function that will be executed right after the typeform is successfully submitted.
* @param {Object} event - Event payload.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('build-options-from-attributes', () => {
data-tf-disable-tracking
data-tf-disable-auto-focus
data-tf-on-ready="onTypeformReady"
data-tf-on-started="onTypeformStarted"
data-tf-on-submit="onTypeformSubmit"
data-tf-on-question-changed="onTypeformQuestionChanged"
data-tf-on-height-changed="onTypeformHeightChanged"
Expand All @@ -37,6 +38,7 @@ describe('build-options-from-attributes', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const win = window as any
win.onTypeformReady = jest.fn()
win.onTypeformStarted = jest.fn()
win.onTypeformSubmit = jest.fn()
win.onTypeformQuestionChanged = jest.fn()
win.onTypeformHeightChanged = jest.fn()
Expand All @@ -53,6 +55,7 @@ describe('build-options-from-attributes', () => {
opacity: 50,
disableTracking: true,
onReady: win.onTypeformReady,
onStarted: win.onTypeformStarted,
onSubmit: win.onTypeformSubmit,
onQuestionChanged: win.onTypeformQuestionChanged,
onHeightChanged: win.onTypeformHeightChanged,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const buildOptionsFromAttributes = (element: HTMLElement) => {
opacity: 'integer',
disableTracking: 'boolean',
onReady: 'function',
onStarted: 'function',
onSubmit: 'function',
onQuestionChanged: 'function',
onHeightChanged: 'function',
Expand Down
8 changes: 8 additions & 0 deletions packages/embed/src/utils/create-iframe/create-iframe.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('create-iframe', () => {
const triggerIframeRedrawMock = jest.spyOn(require('./trigger-iframe-redraw'), 'triggerIframeRedraw')
const options = {
onReady: jest.fn(),
onStarted: jest.fn(),
onSubmit: jest.fn(),
onQuestionChanged: jest.fn(),
onHeightChanged: jest.fn(),
Expand Down Expand Up @@ -84,6 +85,13 @@ describe('create-iframe', () => {
expect(options.onReady).toBeCalled()
})

it('should call form-started handler', async () => {
window.postMessage({ type: 'form-started', embedId: 'random-id' }, '*')
await new Promise((resolve) => setTimeout(resolve))

expect(options.onStarted).toBeCalled()
})

it('should call form-screen-changed handler', async () => {
window.postMessage({ type: 'form-screen-changed', embedId: 'random-id' }, '*')
await new Promise((resolve) => setTimeout(resolve))
Expand Down
3 changes: 3 additions & 0 deletions packages/embed/src/utils/create-iframe/create-iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
getFormHeightChangedHandler,
getFormThemeHandler,
getThankYouScreenButtonClickHandler,
getFormStartedHandler,
} from './get-form-event-handler'
import { triggerIframeRedraw } from './trigger-iframe-redraw'
import { dispatchCustomKeyEventFromIframe } from './setup-custom-keyboard-close'
Expand All @@ -28,6 +29,7 @@ export const createIframe = (type: EmbedType, { formId, domain, options }: Creat
const {
iframeProps = {},
onReady,
onStarted,
onQuestionChanged,
onHeightChanged,
onSubmit,
Expand Down Expand Up @@ -57,6 +59,7 @@ export const createIframe = (type: EmbedType, { formId, domain, options }: Creat
}

window.addEventListener('message', getFormReadyHandler(embedId, onReady))
window.addEventListener('message', getFormStartedHandler(embedId, onStarted))
window.addEventListener('message', getFormQuestionChangedHandler(embedId, onQuestionChanged))
window.addEventListener('message', getFormHeightChangedHandler(embedId, onHeightChanged))
window.addEventListener('message', getFormSubmitHandler(embedId, onSubmit))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ export const getFormReadyHandler = (embedId: string, callback?: callbackFn) => {
return getFormEventHandler('form-ready', embedId, callback)
}

export const getFormStartedHandler = (embedId: string, callback?: callbackFn) => {
return getFormEventHandler('form-started', embedId, callback)
}

export const getFormQuestionChangedHandler = (embedId: string, callback?: callbackFn) => {
return getFormEventHandler('form-screen-changed', embedId, callback)
}
Expand Down

0 comments on commit e44b5e7

Please sign in to comment.