# # PDF Form API 迁移指南

本章节旨在帮助开发者从 Foxit PDF SDK for Web 旧版本（10.0.0 或更早版本）迁移到最新版本，主要关注的是表单模块的迁移。迁移过程中会涉及到 API 的变更、功能的差异以及兼容性问题，请仔细阅读并遵循本指南，以确保迁移的顺利进行。

## # 迁移步骤

1. 评估当前状态

   - 识别当前所使用的 SDK 版本：确认当前使用的 SDK 版本为 10.0.0 或更早版本。
   - 审查现有代码：检查所有涉及 PDF 表单操作的代码，确保了解当前实现的功能和依赖性。

2. 安装新版本 SDK

   使用以下命令安装最新版本的 SDK：

       npm i --save @foxitsoftware/foxit-pdf-sdk-for-web@latest

3. API 映射

   - 创建表单域：

     - 旧版本：

           const doc = pdfViewer.getCurrentPDFDoc();
           await doc.loadPDFForm();
           const form = doc.getPDFForm();

           const pageIndex = 0;
           const fieldName = "Push Button";
           const fieldType = PDF.form.constant.Field_Type.PushButton;
           const rect = {
               left: 0,
               right: 100,
               top: 100,
               bottom: 0
           };
           await form.addControl(
               pageIndex,
               fieldName,
               fieldType,
               rect
           );

     - 新版本：

           const doc = pdfViewer.getCurrentPDFDoc();
           const form = doc.getPDFForm();
           const pdfRect = {
               left: 0,
               right: 100,
               top: 0,
               bottom: 100
           };
           await form.createPushButton({
               pdfRect,
               pageIndex: 0,
               rotate: 0,
           });

           await form.createTextField({
               pdfRect,
               pageIndex: 0,
               rotate: 0,
           });

           await form.createImageButton({
               pdfRect,
               pageIndex: 0,
               rotate: 0,
               imagePath: 'https://example.com/image.png'
           });
           await form.createDatetime({
               pdfRect,
               pageIndex: 0,
               rotate: 0,
               timeformat: 'yyyy-mm-DD'
           });
           await form.createCheckbox({
               pdfRect,
               pageIndex: 0,
               rotate: 0
           });
           await form.createRadioButton({
               pdfRect,
               pageIndex: 0,
               rotate: 0
           });
           await form.createComboBox({
               pdfRect,
               pageIndex: 0,
               rotate: 0
           });
           await form.createListBox({
               pdfRect,
               pageIndex: 0,
               rotate: 0
           });
           await form.createSignature({
               pdfRect,
               pageIndex: 0,
               rotate: 0
           });

   - 删除表单域：

     - 旧版本：

           const doc = pdfViewer.getCurrentPDFDoc();
           const form = doc.getPDFForm();
           // 删除表单字段及其所有表单域
           await form.removeField("Push Button0");

     - 新版本：

           const doc = pdfViewer.getCurrentPDFDoc();
           const page = await doc.getPageByIndex(0);
           // 删除指定表单域，若该表单域所属字段无其他表单域，则字段也会被自动删除
           const widgetObjNumber = 881;
           await page.removeAnnotByObjectNumber(widgetObjNumber);

   - 获取表单字段：

     - 旧版本：

           const doc = pdfViewer.getCurrentPDFDoc();
           const form = doc.getPDFForm();
           // 按索引获取表单字段
           const field = form.getFieldByIndex(0);
           // 按名称前缀获取表单字段列表
           const fields = form.getField("Push Button0");

     - 新版本：

           const doc = pdfViewer.getCurrentPDFDoc();
           const form = doc.getPDFForm();
           // 按名称精确获取表单字段，如果该字段不存在，将会抛出异常
           const field = await form.getField("Push Button0");
           // 获取所有表单字段
           const allFields = await form.getFields();
           // 按名称前缀获取表单字段列表
           const fields = await form.getFieldsByNamePrefix("Push Button");
           // 按页面索引和坐标获取表单字段
           const fieldAtPosition = await form.getFieldAtPosition(0, { x: 0, y: 0 });

4. 表单域和字段属性读取与变更

   新版本中，属性读取方法由同步改为异步。

   - 旧版本：

         const doc = pdfViewer.getCurrentPDFDoc();
         const form = doc.getPDFForm();
         const field = form.getFieldByIndex(0);

         const mappingName = field.getMappingName();
         const alternateName = field.getAlternateName();
         const value = field.getValue();
         const alignment = field.getAlignment();
         const options = field.getOptions();
         const maxLength = field.getMaxLength();
         const type = field.getType();

   - 新版本：

         const doc = pdfViewer.getCurrentPDFDoc();
         const form = doc.getPDFForm();
         const field = form.getFieldByIndex(0);

         const mappingName = await field.getMappingName();
         const alternateName = await field.getAlternateName();
         const value = await field.getValue();
         const alignment = await field.getAlignment();
         const options = await field.getOptions();
         const maxLength = await field.getMaxLength();
         const type = await field.getType();

         // 新增接口
         await field.getDefaultValue();
         await field.isCheckedByDefault();
         await field.getWidgetsCount();
         await field.getWidget(0);
         await field.isRequired();
         await field.isReadonly();
         await field.getDateTimeFormat();
         await field.getValidateActionInfo();
         await field.getCalculateActionInfo();
         const { type, isImage, isDateOrTime } = await field.getExtType();

5. 事件变更

   - ViewerEvents.focusOnControl

     - 旧版本：

           pdfViewer.eventEmitter.on(ViewerEvents.focusOnControl control => {
               // 此处 control 的类型为 PDFControl
           })

     - 新版本：

           // 新版本调整了事件参数类型
           pdfViewer.eventEmitter.on(ViewerEvents.focusOnControl, widget  => {
               // 此处 widget 的类型为 Widget
           })

6. Action 接口变更

   请参考 PDF Action 接口迁移指南。

7. 签名流程接口变更

   请参考 签名流程接口迁移指南。

8. UI 实现变更

   涉及以下 UI 组件的变更：

   - 表单域右键菜单
   - 表单域属性对话框
   - 由动作触发的 UI 组件（alert 弹窗、 confirm 弹窗、 弹出菜单等）

   在新版本中，这些组件都支持自定义。您可以参考各个组件的自定义文档：

   - 自定义表单域右键菜单
   - 自定义表单域日期选择控件
   - 自定义表单域属性对话框
   - 自定义由动作触发的 UI 组件
   - 自定义签名域UI