Webサイトやアプリの中で、フォームを使いたいと思うケースは多いです。お問い合わせのようなものもあれば、アンケートであったり、クイズなどもあります。フォームを使う機会は多いので、なるべく汎用的な実装ができると便利です。
今回はフォームを手軽に作成できるSurveyJSを紹介します。いくつかの機能は有料なので、注意してください。
SurveyJSとは
SurveyJSは、JavaScriptで動作するフォーム作成ライブラリです。

素のJavaScriptはもちろん、ReactやVue、Angularなどのフレームワークでも利用できます。無料で使える機能も多いですが、企業で利用する場合は有料ライセンスが必要になることがあります。
料金体系は大きく分けて4つあります。
- 無料
フォームライブラリ - Basic(年間499ユーロ)
サーベイクリエイター - Pro(年間899ユーロ)
PDFエクスポート、ダッシュボード - Enterprise(1,998ユーロより)
サポートなど
SurveyJSの使い方
今回は素のJavaScriptでの使い方を紹介します。まず、基本になるHTMLは以下のようになります。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SurveyJS Demo</title>
<!-- 必要なライブラリ -->
<link href="https://unpkg.com/survey-core/survey-core.min.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/survey-core/survey.core.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/survey-js-ui/survey-js-ui.min.js"></script>
</head>
<body>
<div id="surveyContainer"></div>
<script src="app.js"></script>
<div id="surveyResult"></div>
</body>
</html>
そして、JavaScriptは以下のようになります。まず、フォームの内容(モデル)をJSONで定義します。
const surveyJson = {
elements: [{
name: "FirstName",
title: "Enter your first name:",
type: "text"
}, {
name: "LastName",
title: "Enter your last name:",
type: "text"
}]
};
このモデルを使って、SurveyJSのSurveyクラスのインスタンスを作成します。
const survey = new Survey.Model(surveyJson);
さらにこのインスタンスをHTMLの要素に紐付け、フォームの内容を出力します。
document.addEventListener("DOMContentLoaded", function() {
survey.render(document.getElementById("surveyContainer"));
});
これでフォームが表示されます。

あとは、フォームの送信イベントをキャッチして、入力内容を取得します。
function alertResults(survey) {
document
.getElementById("surveyResult")
.innerHTML = "Result JSON:\n" + JSON.stringify(survey.data);
}
// フォーム送信イベントの登録
survey.onComplete.add(alertResults);

ページ分け
フォームが長くなる場合、ページを分けることもできます。ページを分けるには、モデルのJSONにpagesプロパティを追加します。
const surveyJson = {
pages: [{
elements: [{
name: "satisfaction-score",
title: "How would you describe your experience with our product?",
type: "radiogroup",
choices: [
{ value: 5, text: "Fully satisfying" },
{ value: 4, text: "Generally satisfying" },
{ value: 3, text: "Neutral" },
{ value: 2, text: "Rather unsatisfying" },
{ value: 1, text: "Not satisfying at all" }
],
isRequired: true
}]
}, {
elements: [{
name: "what-would-make-you-more-satisfied",
title: "What can we do to make your experience more satisfying?",
type: "comment",
}, {
name: "nps-score",
title: "On a scale of zero to ten, how likely are you to recommend our product to a friend or colleague?",
type: "rating",
rateMin: 0,
rateMax: 10
}],
}, {
elements: [{
name: "how-can-we-improve",
title: "In your opinion, how could we improve our product?",
type: "comment"
}],
}, {
elements: [{
name: "disappointing-experience",
title: "Please let us know why you had such a disappointing experience with our product",
type: "comment"
}],
}]
};
これで、ページが分かれたフォームが作成できます。ページの移動は自動的に行われます。

フォーム作成
SurveyJSにはフォームをGUIで作成できるSurvey Creatorがあります。試用はできますが、実際に利用する場合は有料ライセンスが必要です。
まず、以下のようなHTMLを用意します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SurveyJS Demo</title>
<!-- SurveyJS Form Library resources -->
<link href="https://unpkg.com/survey-core/survey-core.min.css" type="text/css" rel="stylesheet">
<script src="https://unpkg.com/survey-core/survey.core.min.js"></script>
<script src="https://unpkg.com/survey-js-ui/survey-js-ui.min.js"></script>
<!-- (Optional) Predefined theme configurations -->
<script src="https://unpkg.com/survey-core/themes/index.min.js"></script>
<!-- Survey Creator resources -->
<link href="https://unpkg.com/survey-creator-core/survey-creator-core.min.css" type="text/css" rel="stylesheet">
<script src="https://unpkg.com/survey-creator-core/survey-creator-core.min.js"></script>
<script src="https://unpkg.com/survey-creator-js/survey-creator-js.min.js"></script>
<!-- ... -->
</head>
<body>
<div id="surveyCreator" style="height: 100vh;"></div>
</body>
<script src="creator.js"></script>
</html>
creator.js
は以下のようになります。
// Survey Creatorのオプション
const creatorOptions = {
autoSaveEnabled: true,
collapseOnDrag: true
};
// Survey Creatorのインスタンスを作成
const creator = new SurveyCreator.SurveyCreator(creatorOptions);
// ページが読み込まれたら、Survey Creatorを表示
document.addEventListener("DOMContentLoaded", function() {
creator.render(document.getElementById("surveyCreator"));
});
フォームの項目はドラッグ&ドロップで作成できます。Googleフォームのような感じですが、より自由度が高い印象です。

項目ができあがったら、JSON形式でエクスポートできます。あとは、このJSONを先ほどのフォーム表示のコードに組み込めば、同じフォームが表示されます。

PDFエクスポート
PDFエクスポートも有料ライセンスが必要です。PDFエクスポートを利用するには、jsPDF
ライブラリを追加します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SurveyJS Demo</title>
<link href="https://unpkg.com/survey-core/survey-core.min.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/survey-core/survey.core.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/survey-js-ui/survey-js-ui.min.js"></script>
<!-- jsPDF library -->
<script type="text/javascript" src="https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js"></script>
<!-- SurveyJS PDF Generator library -->
<script type="text/javascript" src="https://unpkg.com/survey-pdf/survey.pdf.min.js"></script>
</head>
<body>
<div id="surveyContainer"></div>
<script type="module" src="pdf.js"></script>
</body>
</html>
まずフォームを表示するところまでは同じです。
const surveyJson = {
/** 省略 */
};
const survey = new Survey.Model(surveyJson);
survey.addNavigationItem({
id: "pdf-export",
title: "Save as PDF",
action: () => savePdf(survey.data)
});
document.addEventListener("DOMContentLoaded", function () {
survey.render(document.querySelector("#surveyContainer"));
});
survey.addNavigationItem
でナビゲーションにPDFエクスポートの項目を追加しています。

クリックされたら savePdf
関数が呼ばれます。
const savePdf = async function (surveyData) {
const pdfDocOptions = {
fontSize: 12,
};
const surveyPdf = new SurveyPDF.SurveyPDF(surveyJson, pdfDocOptions);
surveyPdf.data = surveyData;
surveyPdf.save();
};
これでPDFファイルがダウンロードされます。

日本語フォントへの対応
デフォルトのままでは、日本語が文字化けしてしまいます。日本語フォントを利用するには、まず日本語フォントを用意します。今回はGoogle FontsのNoto Sans JPをダウンロードしました。
これを適当な場所(今回はルート)に配置します。そして、このファイルを読み込んで、Base64エンコードします。例えば以下のような関数で、ファイルを読み込んでBase64エンコードされた文字列を取得できます。
async function fetchBinaryToBase64String(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(HTTP error! status: ${response.status}
);
}
const buffer = await response.arrayBuffer();
const uint8Array = new Uint8Array(buffer);
let binary = '';
const len = uint8Array.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(uint8Array[i]);
}
const base64String = btoa(binary);
return base64String;
}
そして、この文字列をフォントとして指定します。
const savePdf = async function (surveyData) {
const pdfDocOptions = {
fontSize: 12,
fontName: 'notoSansJP', // フォント名を指定
};
// フォントをダウンロード&Base64エンコード
const base64 = await fetchBinaryToBase64String('/NotoSansJP-Regular.ttf');
// フォントを登録
SurveyPDF.DocController.addFont("notoSansJP", base64, "normal");
SurveyPDF.DocController.addFont("notoSansJP", base64, "bold");
// あとは同じ
const surveyPdf = new SurveyPDF.SurveyPDF(surveyJson, pdfDocOptions);
surveyPdf.data = surveyData;
surveyPdf.save();
};
これで日本語が正しく表示されるPDFが生成されます。

まとめ
SurveyJSを使うと、手軽にフォームを作成できます。とても多機能なので、大抵のニーズに対応できるでしょう。有料の機能も使えば、誰でもフォームを作成できたり、PDFエクスポートできるフォームも作れたりします。
ぜひ試してみてください。