Open7
Next.js上でformBuilderを使ってみる
- ドラッグ&ドロップでフォームを作成・編集できるjQueryプラグイン
- 多くの設定オプションやアクションを用意
- フォームの質問項目をXML、JSON形式で出力することが可能
Reactのサンプルもある
今回はオンラインコードエディタのstackblitzを使用してNext14上で動かしていく。
コードだけ見たい方はこちらから
Next以外にもReact,Vue,Angularなどもあるので、フロントエンドのデモを試すときにオススメ
準備
パッケージをインストール
$ yarn add formBuilder
Homeコンポーネントの不要なものを削除
"use client"
export default function Home() {
return (
<main>
<h1>formbuilder</h1>
</main>
);
}
必要最低限のものだけ削除
layout.tsxのglobals.cssの読み込みを削除しておいた方が見やすい
useRefを使用するので"use client
も一緒に記述
必要なものをインポート
import $ from 'jquery';
import React, { useEffect, useRef } from 'react';
export default function Home() {
// 省略
}
公式のドキュメントでは一緒にNodeのrequireを使用してインポートしているが、タイミングの都合でうまく動かない。後ほどuseEffect内で記述する。
importとrequreiの違いについては
→
ロジック部分の記述
export default function Home() {
const fbRef = useRef<HTMLDivElement | null>(null); // フォーム編集の中身を保持
useEffect(() => {
window.jQuery = $;
window.$ = $;
require('jquery-ui-sortable');
require('formBuilder');
// jQuery 関連のコードを実行
($ as any)(fbRef.current).formBuilder({});
}, []);
return (
// 省略
);
}
中身を保持するrefとjQueryのインポートをここで行う。
useEffectを使用して初回のみ走らせるようにする。
描画の記述
export default function Home() {
const fbRef = useRef<HTMLDivElement | null>(null);
const isInitializedForm = useRef(false);
useEffect(() => {
if (isInitializedForm.current) return;
// 省略
}, []);
return (
<main>
<h1>formbuilder</h1>
<div id="fb-editor" ref={fbRef} />
</main>
);
}
まずは1つ前で定義したfbRef
を使用して<div id="fb-editor" ref={fbRef} />
を追記
これで画面上にフォームビルダーを描画することができた。
しかし現状の実装だとfbRefに変更が入るたびにformBuilder({})
が発火してフォームビルダーが増殖する。
それを防ぐために初期化フラグを持つ変数を用意して、if文の早期リターンで初期化時のみformBuilder({})
が実行されるようにする。
フォームデータの出力
既存で実装されているClear
と[{...}]
は実際にクリアとjsonの中身を表示するよう動くがSave
だけは保存したり出力されりしない。
そのため個別で作る準備としてClearとSaveとDataを非表示にする
($ as any)(fbRef.current).formBuilder({disabledActionButtons: ['data', 'save']});
プロパティ 'jQuery' は型 'Window & typeof globalThis' に存在しません。
という指摘を解消する
方法1
global.d.ts
export {};
declare global {
interface Window {
jQuery: typeof import('jquery');
$: typeof import('jquery');
}
}
方法2
index.tsx
interface Window {
jQuery: typeof import('jquery');
$: typeof import('jquery');
}
declare var window: Window;