You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中使用jsPDF+html2canvas导出含输入框的表格为PDF时输入值不显示

问题根源定位

html2canvas的渲染逻辑是爬取DOM的静态结构生成canvas,原生input、textarea、select这类表单控件的用户输入值,存储在元素的运行时value属性中,不会写入DOM的静态文本节点,因此html2canvas抓取时只能识别到输入框的边框、初始占位符,完全读不到用户手动输入的动态内容,这就是表格加了输入框后导出内容缺失的核心原因。

另外当前HTML结构存在规范问题:table标签内直接嵌套div块级元素,不符合HTML标准,浏览器渲染时会自动把这些div移出table的DOM层级,这也是之前更换form标签后导出仍然出现错位、内容不全的次要原因,建议把外层table替换为普通div容器,通过CSS实现表格布局效果,避免浏览器自动重排DOM。

适配现有技术栈的修复方案(jsPDF + html2canvas)

核心思路是:导出触发时,把所有输入框的当前值临时转换成同位置的静态文本节点,隐藏原始input元素,等html2canvas完成渲染生成canvas后,再恢复原始输入框的显示,全程不影响页面的正常交互。
改造后的代码如下:

pdfCreationClick() {
  const doc = new jspdf.jsPDF('p','mm','a4');   
  doc.text("this is siva",15,15);
  const targetContainer = document.getElementById('secondTable') as HTMLElement;

  // 临时镜像所有输入框的当前值
  const tempReplaceList: Array<{originInput: HTMLInputElement, tempNode: HTMLElement}> = [];
  targetContainer.querySelectorAll('input').forEach(inputEl => {
    const currentValue = inputEl.value;
    // 创建和原输入框尺寸、样式完全一致的静态文本节点
    const tempTextNode = document.createElement('span');
    tempTextNode.textContent = currentValue;
    const inputStyle = getComputedStyle(inputEl);
    tempTextNode.style.cssText = `
      display: inline-block;
      width: ${inputEl.offsetWidth}px;
      height: ${inputEl.offsetHeight}px;
      padding: ${inputStyle.padding};
      border: none;
      font: ${inputStyle.font};
      color: ${inputStyle.color};
      line-height: ${inputStyle.lineHeight};
    `;
    // 临时隐藏原输入框,插入静态文本节点
    inputEl.style.visibility = 'hidden';
    inputEl.parentNode?.appendChild(tempTextNode);
    tempReplaceList.push({originInput: inputEl, tempNode: tempTextNode});
  });

  // 执行原有渲染逻辑
  html2canvas(targetContainer).then((canvas) => {
    // 渲染完成后恢复原输入框的显示
    tempReplaceList.forEach(({originInput, tempNode}) => {
      tempNode.remove();
      originInput.style.visibility = '';
    });

    const imgWidth = 208;
    const imgData = canvas.toDataURL('image/png');
    const imgHeight = canvas.height * imgWidth / canvas.width;
    doc.addImage(imgData, 'PNG', 0, 0, 208, imgHeight);
    doc.save('first.pdf');
  })
}

更稳定的替代导出方案(无截图类问题)

不需要依赖DOM截图渲染,直接利用组件的双向绑定数据源dataarray,通过jsPDF的原生表格生成能力,绘制矢量格式的表格内容,彻底规避输入框值读取不到的问题,同时导出的PDF文件更小、文本更清晰。
实现代码示例:

pdfCreationClick() {
  const doc = new jspdf.jsPDF('p','mm','a4');
  doc.text("this is siva", 15, 15);
  // 定义表格列配置
  const tableHeader = [['序号', '产品', '描述', '数量', '单价', '金额', '税率']];
  // 直接从组件数据源读取用户填写的内容(因为有[(ngModel)]双向绑定,数据实时同步)
  const tableBody = this.dataarray.map((item, index) => [
    index + 1,
    item.product,
    item.description,
    item.quantity,
    item.rate,
    item.rate * item.quantity,
    item.tax
  ]);
  // 绘制矢量表格
  (doc as any).autoTable({
    startY: 20,
    head: tableHeader,
    body: tableBody,
    theme: 'grid'
  });
  doc.save('first.pdf');
}

该方案的优势:

  • 完全和DOM渲染逻辑解耦,不存在输入框值丢失的问题,用户输入的内容会通过双向绑定实时同步到ts变量中,读取即可使用
  • 导出的PDF为矢量文本格式,放大不会出现模糊问题,文件体积比截图式导出小70%以上
  • 不受HTML结构是否符合规范的影响,不会出现内容错位

内容的提问来源于stack exchange,提问作者Siva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.01 19:54:05