Angular2 GWT 集成的意外指令值错误

Unexpected directive value error with Angular2 GWT integration

我正在尝试在 GWT 2.6.0

中使用 Angular2(仅 JavaScript,没有 TypeScript)

有一个像这样的非常基本的代码:

public native void init() /*-{
  var MyComp= $wnd.ng.Component({
  selector: 'my-sample',
  properties:['model']
  })
  .View({
  directives: [], 
  template: '\n<h1>Hello world!</h1>'
  })
  .Class({
    constructor: function() {
    }
  });
  var MyApp= $wnd.ng.Component({selector:'my-app'})
  .View({
    directives: [MyComp],
    template:'<my-sample></my-sample>'
  })
  .Class({
    constructor:function(){}
  });
  $wnd.setTimeout(function() { $wnd.ng.bootstrap(MyApp);}, 1000);
}-*/;

但是我的模板中的 导致了这个错误:

angular2.sfx.dev.js:33004 EXCEPTION: Unexpected directive value 'function (){' on the View of component 'function (){'System.register.BrowserDomAdapter.logError @ angular2.sfx.dev.js:33004System.register.BrowserDomAdapter.logGroup @ angular2.sfx.dev.js:33015System.register.ExceptionHandler.call @ angular2.sfx.dev.js:4792(anonymous function) @ angular2.sfx.dev.js:28798System.register.NgZone._onError @ angular2.sfx.dev.js:11072System.register.NgZone._createInnerZone.errorHandling.onError @ angular2.sfx.dev.js:10991run @ angular2.sfx.dev.js:141System.register.NgZone._createInnerZone.zone.fork.fork.$run @ angular2.sfx.dev.js:11005zoneBoundFn @ angular2.sfx.dev.js:111lib$es6$promise$$internal$$tryCatch @ angular2.sfx.dev.js:1507lib$es6$promise$$internal$$invokeCallback @ angular2.sfx.dev.js:1519lib$es6$promise$$internal$$publish @ angular2.sfx.dev.js:1490(anonymous function) @ angular2.sfx.dev.js:219System.register.NgZone._createInnerZone.zone.fork.fork.$scheduleMicrotask.microtask @ angular2.sfx.dev.js:11031run @ angular2.sfx.dev.js:138System.register.NgZone._createInnerZone.zone.fork.fork.$run @ angular2.sfx.dev.js:11005zoneBoundFn @ angular2.sfx.dev.js:111lib$es6$promise$asap$$flush @ angular2.sfx.dev.js:1301
angular2.sfx.dev.js:33004 STACKTRACE:System.register.BrowserDomAdapter.logError @ angular2.sfx.dev.js:33004System.register.ExceptionHandler.call @ angular2.sfx.dev.js:4794(anonymous function) @ angular2.sfx.dev.js:28798System.register.NgZone._onError @ angular2.sfx.dev.js:11072System.register.NgZone._createInnerZone.errorHandling.onError @ angular2.sfx.dev.js:10991run @ angular2.sfx.dev.js:141System.register.NgZone._createInnerZone.zone.fork.fork.$run @ angular2.sfx.dev.js:11005zoneBoundFn @ angular2.sfx.dev.js:111lib$es6$promise$$internal$$tryCatch @ angular2.sfx.dev.js:1507lib$es6$promise$$internal$$invokeCallback @ angular2.sfx.dev.js:1519lib$es6$promise$$internal$$publish @ angular2.sfx.dev.js:1490(anonymous function) @ angular2.sfx.dev.js:219System.register.NgZone._createInnerZone.zone.fork.fork.$scheduleMicrotask.microtask @ angular2.sfx.dev.js:11031run @ angular2.sfx.dev.js:138System.register.NgZone._createInnerZone.zone.fork.fork.$run @ angular2.sfx.dev.js:11005zoneBoundFn @ angular2.sfx.dev.js:111lib$es6$promise$asap$$flush @ angular2.sfx.dev.js:1301
angular2.sfx.dev.js:33004 Error: Unexpected directive value 'function (){' on the View of component 'function (){'
    at new BaseException (http://127.0.0.1:8888/angular2demo/angular2.sfx.dev.js:25289:21)
    at RuntimeMetadataResolver.System.register.RuntimeMetadataResolver.getViewDirectivesMetadata (http://127.0.0.1:8888/angular2demo/angular2.sfx.dev.js:13091:17)
    at RuntimeCommandFactory.componentTemplateFactory (http://127.0.0.1:8888/angular2demo/angular2.sfx.dev.js:36943:66)
    at RuntimeCommandFactory.System.register.RuntimeCommandFactory.createBeginComponent (http://127.0.0.1:8888/angular2demo/angular2.sfx.dev.js:12451:33)
    at CommandBuilderVisitor.System.register.CommandBuilderVisitor.visitElement (http://127.0.0.1:8888/angular2demo/angular2.sfx.dev.js:12572:46)
    at ElementAst.System.register.ElementAst.visit (http://127.0.0.1:8888/angular2demo/angular2.sfx.dev.js:11797:22)
    at http://127.0.0.1:8888/angular2demo/angular2.sfx.dev.js:11876:27
    at Array.forEach (native)
    at Object.templateVisitAll (http://127.0.0.1:8888/angular2demo/angular2.sfx.dev.js:11875:10)
    at CommandCompiler.System.register.CommandCompiler.compileComponentRuntime (http://127.0.0.1:8888/angular2demo/angular2.sfx.dev.js:12400:22)

我刚刚取出本机代码并粘贴到非 GWT 应用程序 HTML 文件脚本标记中(只需将 $wnd 替换为 window),一切正常。

这是什么错误,我该如何解决?

2016/03/22: 在 Eric 的回应之后,我尝试使用 UMD 包,现在在 GWT 中生成了这样的代码。

public native void init() /*-{
    if (!$wnd.SampleApp)
        $wnd.SampleApp = {}
    $wnd.SampleApp.SampleComponent =
      $wnd.ng.core.Component({
          selector: 'my-sample',
    template: '\n<h1>Hello world!</h1>'
          })
          .Class({
            constructor: function() {}
          });
    $wnd.SampleApp.Main =
    $wnd.ng.core.Component({
        selector: 'my-app',
        directives: [$wnd.SampleApp.SampleComponent],
        template: '<h1>My First Angular 2 App</h1>'
    })
    .Class({
    constructor: function() {}
    });
    setTimeout(function() {
        $wnd.ng.platform.browser.bootstrap($wnd.SampleApp.Main);
    }, 3000);
}-*/;

但还是报错:

EXCEPTION: Unexpected directive value 'class0' on the View of component 'class1'
browser_adapter.ts:73 EXCEPTION: Unexpected directive value 'class0' on the View of component 'class1'BrowserDomAdapter.logError @ browser_adapter.ts:73BrowserDomAdapter.logGroup @ browser_adapter.ts:84ExceptionHandler.call @ exception_handler.ts:49(anonymous function) @ application_ref.ts:262NgZone._notifyOnError @ ng_zone.ts:453collection_1.StringMapWrapper.merge.onError @ ng_zone.ts:352Zone.run @ angular2-polyfills.js:1247(anonymous function) @ ng_zone.ts:370zoneBoundFn @ angular2-polyfills.js:1220lib$es6$promise$$internal$$tryCatch @ angular2-polyfills.js:468lib$es6$promise$$internal$$invokeCallback @ angular2-polyfills.js:480lib$es6$promise$$internal$$publish @ angular2-polyfills.js:451(anonymous function) @ angular2-polyfills.js:123microtask @ ng_zone.ts:409Zone.run @ angular2-polyfills.js:1243(anonymous function) @ ng_zone.ts:370zoneBoundFn @ angular2-polyfills.js:1220lib$es6$promise$asap$$flush @ angular2-polyfills.js:262
browser_adapter.ts:73 STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.ts:73ExceptionHandler.call @ exception_handler.ts:52(anonymous function) @ application_ref.ts:262NgZone._notifyOnError @ ng_zone.ts:453collection_1.StringMapWrapper.merge.onError @ ng_zone.ts:352Zone.run @ angular2-polyfills.js:1247(anonymous function) @ ng_zone.ts:370zoneBoundFn @ angular2-polyfills.js:1220lib$es6$promise$$internal$$tryCatch @ angular2-polyfills.js:468lib$es6$promise$$internal$$invokeCallback @ angular2-polyfills.js:480lib$es6$promise$$internal$$publish @ angular2-polyfills.js:451(anonymous function) @ angular2-polyfills.js:123microtask @ ng_zone.ts:409Zone.run @ angular2-polyfills.js:1243(anonymous function) @ ng_zone.ts:370zoneBoundFn @ angular2-polyfills.js:1220lib$es6$promise$asap$$flush @ angular2-polyfills.js:262
browser_adapter.ts:73 Error: Unexpected directive value 'class0' on the View of component 'class1'
    at new BaseException (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:4377:24)
    at RuntimeMetadataResolver.getViewDirectivesMetadata (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:26882:24)
    at TemplateCompiler._compileNestedComponentRuntime (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:21535:66)
    at http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:21520:88
    at Array.forEach (native)
    at Array.forEach (http://127.0.0.1:8888/angular2demo/es6-shim.min.js:10:16878)
    at http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:21520:44
    at Zone.run (http://127.0.0.1:8888/angular2demo/angular2-polyfills.js:1243:24)
    at Zone.run (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:13235:43)
    at zoneBoundFn (http://127.0.0.1:8888/angular2demo/angular2-polyfills.js:1220:26)

-----async gap-----
Error
    at _getStacktraceWithUncaughtError (http://127.0.0.1:8888/angular2demo/angular2-polyfills.js:2236:29)
    at Zone.fork (http://127.0.0.1:8888/angular2demo/angular2-polyfills.js:2285:47)
    at Zone.bind (http://127.0.0.1:8888/angular2demo/angular2-polyfills.js:1218:53)
    at bindArguments (http://127.0.0.1:8888/angular2demo/angular2-polyfills.js:1401:36)
    at lib$es6$promise$promise$$Promise.obj.(anonymous function) [as then] (http://127.0.0.1:8888/angular2demo/angular2-polyfills.js:1413:46)
    at TemplateCompiler._compileComponentRuntime (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:21514:19)
    at TemplateCompiler.compileHostComponentRuntime (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:21465:19)
    at RuntimeCompiler_.compileInHost (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:21366:40)
    at DynamicComponentLoader_.loadAsRoot (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:13658:32)
    at di_1.provide.useFactory (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:12500:48)

-----async gap-----
Error
    at _getStacktraceWithUncaughtError (http://127.0.0.1:8888/angular2demo/angular2-polyfills.js:2236:29)
    at Zone.fork (http://127.0.0.1:8888/angular2demo/angular2-polyfills.js:2285:47)
    at NgZone._createInnerZone (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:13223:15)
    at new NgZone (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:13009:37)
    at createNgZone (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:12523:13)
    at PlatformRef_.application (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:12624:34)
    at Object.bootstrap (http://127.0.0.1:8888/angular2demo/angular2-all.umd.dev.js:27196:65)
    at angular2demo-0.js:123:30BrowserDomAdapter.logError @ browser_adapter.ts:73ExceptionHandler.call @ exception_handler.ts:53(anonymous function) @ application_ref.ts:262NgZone._notifyOnError @ ng_zone.ts:453collection_1.StringMapWrapper.merge.onError @ ng_zone.ts:352Zone.run @ angular2-polyfills.js:1247(anonymous function) @ ng_zone.ts:370zoneBoundFn @ angular2-polyfills.js:1220lib$es6$promise$$internal$$tryCatch @ angular2-polyfills.js:468lib$es6$promise$$internal$$invokeCallback @ angular2-polyfills.js:480lib$es6$promise$$internal$$publish @ angular2-polyfills.js:451(anonymous function) @ angular2-polyfills.js:123microtask @ ng_zone.ts:409Zone.run @ angular2-polyfills.js:1243(anonymous function) @ ng_zone.ts:370zoneBoundFn @ angular2-polyfills.js:1220lib$es6$promise$asap$$flush @ angular2-polyfills.js:262

同样,如果我取出这段代码并将其放入 HTML 文件的脚本块中,它就可以工作。所以在 GWT 中 运行 时发生了错误。 GWT代码涉及编译步骤,所以恐怕我不能为它创建一个plnkr。

我希望您的情况不需要 GWT 2.6.0。如果您可以切换到 GWT 2.8.0(还启用 Java 8 支持),还有另一种解决方案。 您是否尝试使用 angular2-gwt (http://lteconsulting.fr/angular2boot/)? 这是一个示例 Angular2Boot 应用程序:https://github.com/ltearno/angular2-gwt。我想你也可以在没有 Spring 后端的情况下使用这个库。

PS: 当前的 GWT 方法建议使用 JsInterop 而不是 JNI。

我能够以一种不太令人信服的方式修复它。对于构造函数,我不得不调用外部 JavaScript 文件来获取函数,而不是仅仅在 JSNI 中定义它们。

语句如下:

  constructor: function() {}

由于某些不兼容性,上述内容会导致此类错误。

我用类似的东西替换了它:

  constructor: $wnd.wrapFunction4GWT(function() {})

其中包装函数将 return 一个继承 GWT 本机层中定义的函数的新函数(因为实时函数不会像这样为空)。