2012-05-04 19 views
2

一般的な目的から非スタティックGWTのJavaメソッドを呼び出すために:JavaScriptからいくつかの非静的Javaメソッドを呼び出す可能性はjavascriptの

説明: JavaアプレットのコードでDOMにGWTのウィジェットを見つけ、それを呼び出すためには、のJavaメソッド(非静的)


JSObject win = JSObject.getWindow(this); 
JSObject doc = (JSObject) win.getMember("document"); 
JSObject gwtWidget = (JSObject) doc.call("getElementsByName", widgetName); 

//todo: have possibility to call `exported` java method over here, smth like: 
//Object[] params = new Object[1]; 
//params[0] = widgetName; 
//Object result = gwtWidget.call("exportedJavaMethod", params); 

//todo: or just call global ($wnd) static JSNI bridge method: 
//Object result = win.call("exportedJavaMethod", params); 
// 

問題は、ウィジェットのIDでウィジェットを見つけることはできませんが、エクスポートされたインスタンス化されたメソッドを持たないDivElementです。


@Export(value="somewidget") 
public class SomeWidget extends SimplePanel implements ..., Exportable { 
    private final String id = "id_some_widget_" + count++; 
    private static int count = 0; 

    public SomeWidget() { 
     getElement().setAttribute("name", id); 
     getElement().setId(id); 
    } 
    ... 

    public static Element getInstanceById(String elementId) { 
     Element someWidget= DOM.getElementById(elementId); 
     return someWidget; 
    } 

    public String getSomeInstancedData() { 
     return "useful_inner_data" + this.id; 
    } 

だから、例えば私がDOMに追加され、具体的なウィジェットを見つけて、JavaScriptで非静的メソッドgetSomeInstancedData()を呼び出すしたいと思います:

マイウィジェットクラスは、(GWT-エクスポート)エクスポート可能です。まったく可能ですか?

と仮定なめらかのように:私が書く基本モジュールで


var someWidget = document.getElementById(widgetId); 
alert(someWidget.getSomeInstancedData()); 

//or: 
var someWidgetExported = com.mypackage.widgets.somewidget.getInstanceById(listenerId); 
alert(someWidgetExported.getSomeInstancedData()); 


ExporterUtil.exportAll(); 

このウィジェットを含むビュー(ViewWithSomeWidget.ui.xml)があります:

 
... 
base:Form 
base:SomeWidget ui:field="someWidget" ... 
... 
/base:SomeWidget 
... 

SomeWidgetがExportableを実装していないとき、プロジェクトは正常に動作しますが、見つかったウィジェットの非静的メソッドを呼び出すことができませんでした。 DIV要素。ためにClassCastExceptionの時間によって

、SomeWidgetがエクスポートを実装して問題を解決するために、しかしよくSomeWidgetとビューをprogect示していないが結合延期の使用:

だから、

ClassCastException: com.mypackage.widgets.SomeWidgetExporterImpl cannot be cast to com.mypackage.widgets.SomeWidget 

、おそらくに他の方法がありますウィジェットのjavascriptオブジェクトを見つけて、それをJavaメソッドにエクスポートしますか?どんな意味でも、どんな考えでも大変感謝しています。代わりに、そのDOM要素を介してウィジェットを取得する最初のグローバルスコープに、そのJavaインスタンスを注入し、それを参照しようとする

答えて

11

javascript関数を宣言すると、非静的メソッドが起動されます。例えば

package com.example; 
public class Layout extends VLayout() { 
    private String nonStaticVar = "nonStaticVar"; 
    public Layout() { 
     declareMethod(this); 
    } 

    //Method which declares non-static method in javascript 
    public native void declareMethod(Layout layout) /*-{ 
     var layout = layout; 
     $wnd.doSomething = function(someString) { 
      [email protected]::doSomething(Ljava/lang/String;)(someString); 
     } 
    }-*/; 

    //Non static method which is being called 
    public String doSomething(String someString) { 
     //Do something, e.g. set var in this instantiated class, or output stuff 
     this.nonStaticVar = someString; 
     Window.alert(someString); 
    } 
} 

、 のdoSomething( "BLA")を呼び出します。 javascriptの は非静的メソッドを呼び出します。

1

:後でより

public class SomeWidget extends SimplePanel implements ..., Exportable { 

    //... 

    public SomeWidget() { 
     getElement().setAttribute("name", id); 
     getElement().setId(id); 

     attachToGlobalScope(id, this); 
    } 

    private native void attachToGlobalScope(String id, SomeWidget instance) /*-{ 
     $wnd.shared[id] = instance; 
    }-*/; 

    //... 
} 

、対応するアプレットのAPI層にフェッチ更新します。

JSObject win = JSObject.getWindow(this); 
JSObject shared = (JSObject) win.getMember("shared"); 
Widget widgetRef = (Widget) shared.getMember(widgetId); 

免責事項:これオブジェクトストレージのために虐待され、一般的に悪い習慣と考えられるが、ここでの唯一の共通範囲として機能しているJavaScriptのグローバルスコープ変数にこのやや曲がったソリューションリレー、、。

+0

問題があることgetElementあります()は宣言されたjavaメソッドを持たないDIV要素を返します...実際、私はすでにほとんど同じ試みを試みました。現在私が使用している解決策は、GWTEventを有効なラップデータで起動する静的メソッド(ブリッジ)を宣言することです。ウィジェットはコンストラクタを購読することで、そのようなイベントを聴くだけです。すべてのウィジェットインスタンスはイベントを取得し、それ自身のIDでフィルタリングします。 – rauch

+0

@rauch、別の回答が受け入れられていることを理解しています –

4

あなたはdiv要素に独自のjsmethodを定義することができ、それはウィジェット法に

@Export(value="somewidget") 
public class SomeWidget extends SimplePanel implements ..., Exportable { 
    private final String id = "id_some_widget_" + count++; 
    private static int count = 0; 

    public SomeWidget() { 
     getElement().setAttribute("name", id); 
     getElement().setId(id); 
     attachInstanceHook(getElement()); 
    } 
    ... 

    public String getSomeInstancedData() { 
     return "useful_inner_data" + this.id; 
    } 


    private native void attachInstanceHook(Element element) /*-{ 
     var elem = element; 
     var widget = this; 
     elem.getWidgetData = function() { 
      [email protected]::getSomeInstancedData()(); 
     }; 

    }-*/; 

を呼び出すことができますし、あなたのjsのコードは次のようになります。

var someWidget = document.getElementById(widgetId); //the id of the div element 
alert(someWidget.getWidgetData());