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

Angular 14中使用tableau-viz Web组件嵌入Tableau失败问题

Angular 14嵌入Tableau Cloud内容的问题解决方案

一、解决tableau-viz被识别为未知元素的问题

Angular默认会将自定义Web组件标记为未知元素,通过以下两步修复:

  1. 添加自定义元素Schema
    在组件所属模块(如app.module.ts)中导入并声明CUSTOM_ELEMENTS_SCHEMA,告知Angular允许使用自定义元素:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA] // 新增配置
})
export class AppModule { }

如果使用独立组件,直接在组件装饰器中添加schemas:

import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppComponent { /* ... */ }
  1. 确保Tableau嵌入脚本加载时机
    直接在index.html引入脚本可能存在加载延迟问题,建议在组件中动态加载脚本,保证Web组件注册完成后再渲染tableau-viz标签:
import { Component, Renderer2, Inject, OnInit } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
  constructor(
    private renderer: Renderer2,
    @Inject(DOCUMENT) private document: Document
  ) {}

  ngOnInit(): void {
    const script = this.renderer.createElement('script');
    script.type = 'module';
    script.src = 'https://10az.online.tableau.com/javascripts/api/tableau.embedding.3.latest.min.js';
    this.renderer.appendChild(this.document.body, script);
  }
}

二、解决JavaScript API嵌入不触发登录弹窗的问题

针对JS API嵌入无登录弹窗的情况,从以下几点排查修复:

  1. 确保Tableau脚本加载完成后初始化Viz
    避免因脚本未加载完成导致tableau对象未定义,调整初始化逻辑:
import { Component, ViewChild, ElementRef, OnInit, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
  @ViewChild("vizContainer") containerDiv!: ElementRef;
  private viz?: tableau.Viz;

  constructor(@Inject(DOCUMENT) private document: Document) {}

  ngOnInit(): void {
    this.loadTableauScript().then(() => this.initTableau());
  }

  private loadTableauScript(): Promise<void> {
    return new Promise((resolve) => {
      if (typeof tableau !== 'undefined') {
        resolve();
        return;
      }
      const script = this.document.createElement('script');
      script.src = 'https://10az.online.tableau.com/javascripts/api/tableau-2.min.js'; // JS API专用脚本
      script.onload = () => resolve();
      this.document.body.appendChild(script);
    });
  }

  private initTableau(): void {
    const vizUrl = "https://10az.online.tableau.com/t/company/views/viewname?:embed=yes&:toolbar=no";

    const options = {
      hideTabs: true,
      authenticationPromptEnabled: true, // 显式开启认证弹窗
      onFirstInteractive: () => {
        console.log("onFirstInteractive");
      },
      onFirstVizSizeKnown: () => {
        console.log("onFirstVizSizeKnown");
      }
    };

    this.viz = new tableau.Viz(
      this.containerDiv.nativeElement,
      vizUrl,
      options
    );
  }
}

注意:JS API和Web组件的脚本不通用,JS API需引入tableau-2.min.js而非嵌入组件的脚本。

  1. 处理Angular安全策略拦截
    Angular的DomSanitizer可能拦截外部资源URL,需将Viz URL标记为安全资源:
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

// 组件构造器注入DomSanitizer
constructor(
  @Inject(DOCUMENT) private document: Document,
  private sanitizer: DomSanitizer
) {}

// 在initTableau中修改URL:
const vizUrl: SafeResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl(
  "https://10az.online.tableau.com/t/company/views/viewname?:embed=yes&:toolbar=no"
);
  1. 检查Tableau Cloud站点配置
    确保Tableau Cloud站点允许外部嵌入:
  • 登录Tableau Cloud进入站点设置
  • 确认"嵌入设置"中允许你的Angular应用域名嵌入内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 00:00:34