如何在Angular 7应用程序中将GWT应用程序用作组件?

时间:2019-04-05 14:32:39

标签: angular gwt angular7 angular-routing smartgwt

我有一个Angular 7应用程序,该应用程序希望将Single Page GWT应用程序用作组件。使用该GWT应用程序作为组件的原因是,我不希望我每次使用Angular路由导航到该应用程序(或页面)时都一次又一次地重新加载GWT应用程序。

这是我尝试过的:

  • 首先,我将该GWT项目的编译后的二进制文件放在Angular应用程序的资产文件夹中。然后,我将所有内容放入Angular应用程序的component.html文件中的index.html标记下。然后添加一个按钮并在其click事件上应用路由器导航,以便单击该按钮将导航到我的Angular应用程序的组件页面。

  • 我将GWT应用程序嵌入到Angular组件的iFrame中。但是我观察到,当通过路由导航到该页面时,每当我使用路由来回导航到该页面和另一个Angular页面时,它就会一次又一次地重新加载。

  • 我还在angular.json文件的 scripts 参数中添加了GWT应用程序所有需要的javascript文件的路径,并将 allowJs 参数修改为true在tsconfig.json中。

  • 我知道在构建Angular项目时会创建main.js文件,其中包含所有组件(包括其路由)的已编译JS代码。因此,我还考虑将GWT的主要nocache.js文件转换为TS文件,但是这导致了很多语法错误,因此我忽略了此过程。

现在,由于我的知识有限,除了上面指定的解决方案外,我无法想到任何解决方案,而且我真的陷于这种情况,无法继续进行我的项目。

那么,任何人都可以帮我找到解决方案吗?我也不确定是否可以这样做。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,那么当您导航到其他路线时,您希望保持活动的角度分量(页面)。

默认情况下,每次进行角度布线时都会破坏该组件,并在返回时再次创建它。这就是为什么它每次都会重新加载。 您需要做的是实现自定义RouteReuseStrategy,以使您的组件保持活动状态。

这是一个非常简单的实现,假设您的GWT应用程序组件具有路由“ gwt”。

export class GwtRouteReuseStrategy extends RouteReuseStrategy {
  private cache: {[key: string]: DetachedRouteHandle} = {};

  public shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return route.url.join('/') === 'gwt';
  }

  public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
    this.cache[route.url.join('/')] = handle;
  }

  public shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return this.cache[route.url.join('/')] != null;
  }

  public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    return this.cache[route.url.join('/')];
  }

  public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
    return future.url.join('/') === 'gwt';
  }
}

您需要在应用程序模块提供程序中提供策略,以便路由器可以使用它。

@NgModule({
  …,
  providers: [
    { provide: RouteReuseStrategy, useClass: GwtRouteReuseStrategy}
  ],
})
export class AppModule {
}

这里也是指向StackBlitz示例的链接,您可以在其中看到它的运行情况。打开控制台,查看“ GwtComponent”在您离开时不会被破坏。

答案 1 :(得分:1)

我要添加另一个答案,以解决第一个答案的注释中提到的问题。问题是,即使RouteReuseStrategy使组件保持活动状态,组件内的iframe仍会重新加载。这可能是由于Angular将其与页面DOM分离,然后重新附加。

一种解决方法是将具有iframe的组件始终保持在主应用程序组件内,并在导航至另一页时将其隐藏。如果导航到要显示的路线,则再次显示它。您可以使用Router events来做到这一点。

这里是实现此替代方法的示例应用程序组件。 gwt组件是带有iFrame的组件。

模板:

<h2><a routerLink="/main">Main</a></h2>
<h2><a routerLink="/gwt">Gwt</a></h2>
<gwt [hidden]="!gwtVisible"></gwt>
<router-outlet [hidden]="gwtVisible"></router-outlet>

代码:

export class AppComponent  {
  gwtVisible = false;

  constructor(router: Router) {
    router.events.subscribe((routerEvent) => {
      if (routerEvent instanceof NavigationEnd) {
        this.gwtVisible = routerEvent.url === '/gwt';
      }
    });
  }
}

从代码中可以看到,当您导航到/gwt路线并显示gwt组件时,应用程序组件会隐藏主要内容,否则它会隐藏并显示{ {1}}。

在路线中,我定义了它导航到一个空的组件,只是为路线router-outlet提供一些东西。

/gwt

我还创建了一个带有工作示例的StackBlitz