Pass element/function handler to gwt function - javascript

I'm using GWT to create a client-side only library. I'm using JSNI to call functions is Java from JS. The issue is I'm trying to pass in an element or a function handler and nothing seems to be happening. I don't get an exceptions from GWT or js. Here's my JSNI function with the bridge.
public static String testMe(Object obj)
{
return "Response to " + obj.toString();
}
public static native void defineBridgeMethod() /*-{
$wnd.testMe = function(msg) {
return #com.mycompany.mywebapp.client.MyWebApp::testMe(Ljava/lang/Object;);
};
}-*/;
Thanks!

You're not using msg, do you mean to call the function with it as a parameter:
public static native void defineBridgeMethod() /*-{
$wnd.testMe = $entry(function(msg) {
return #com.mycompany.mywebapp.client.MyWebApp::testMe(Ljava/lang/Object;)(msg);
});
}-*/;
or you can assign the function directly to window:
public static native void defineBridgeMethod() /*-{
$wnd.testMe = $entry(
#com.mycompany.mywebapp.client.MyWebApp::testMe(Ljava/lang/Object;)
);
}-*/;

The easiest way to export a gwt project to js is using gwt-exporter. Gwtexporter allows to export any gwt project without writing a single line of jsni code and it has plenty of features which allows to customize classes and methods exposed to js, and even it could produce the documentation for your js api.
In your case, implement the Exportable interface in the class with your static method, and annotate your method.
public class MyClass implements Exportable {
#Export("$wnd.testMe")
public static String testMe(Object obj) {
return "Response to " + obj.toString();
}
}
Then you have to call the exportAll() method in your entry point and leave the gwt compiler and gwtexporter generator do their magic
public void onModuleLoad() {
ExporterUtil.exportAll();
}
Here you have a tutorial of how to export a gwt-library to js, although the documentation of the project is quite good.
Some of the projects using this technique are chronoscope, gwtupload(jsupload) and gwtquery(jsquery).

Related

How to configure common data model across android and JS bridge?

I have a JS bridge in Android,
public class WebInterface {
Context mContext;
public WebInterface(Context c) { this.mContext = c;}
#JavascriptInterface
public void showAlert() {
Toast.makeText(mContext, "This is being called from the interface", Toast.LENGTH_SHORT).show();
}
}
I can set interface in my webView,
mWebView.addJavascriptInterface(WebInterface(this), "android");
This works fine for simple methods like showAlert() where the is no params when the params or the param is a simple string but when I need to pass a data model as a params while calling native functions from web app how can I bind data models? I am required to call implement a function with param of type custom data model.
public class WebInterface {
Context mContext;
public WebInterface(Context c) { this.mContext = c;}
#JavascriptInterface
public void showAlert() {
Toast.makeText(mContext, "This is being called from the interface", Toast.LENGTH_SHORT).show();
public void saveData(data: DataModel) { // DataModel is custom model
Toast.makeText(mContext, "Saving data model", Toast.LENGTH_SHORT).show();
}
}
How can I bind data model across native and web app. Is it possible using TypeScript? If so, how to configure? Is it only possible using plain json string as params? no any other way?
You should use the JSON string.
You can create another function receive the format you want, then JSON.stringify the object before pass to the function.
Javascript
function saveData(obj){
const json = JSON.stringify(obj);
Android.saveData(json);
}
Alternative away is used to JSON.parse(data)
javascript
function loadJson(obj) {
var jsonValue = JSON.parse(obj)
Android.saveData(jsonValue)
}

Is it possible to pass a jQuery object as a constructor parameter to a typescript object?

We are trying to figure out a peculiar behaviour of typescript. In the following two code examples, a jQuery object should be altered by typescript. In the example that works fine, we reference the jQuery object by using the selector engine in a method after our typescript class is instantiated. This works:
namespace Company.Module {
export class GenericService {
private statefulObject: JQuery;
public constructor( ) {
}
private _toggleObjectState(): void {
this._statefulObject.toggleClass('text-hide text-success');
}
public SetObjectState(): void {
this.statefulObject = $('#statefulObject');
_toggleObjectState();
}
}
}
Whereas passing the jQuery object in the constructor does not work:
namespace Company.Module {
export class GenericService {
private statefulObject: JQuery;
public constructor( _statefulObject: JQuery ) {
this.statefulObject = _statefulObject;
}
private _toggleObjectState(): void {
this._statefulObject.toggleClass('text-hide text-success');
}
public SetObjectState(): void {
_toggleObjectState();
}
}
}
We would like to understand why this is the case.
Unfortunately this was a non-issue. Our code did not work because we were referencing an object that was added to the DOM dynamically. When passed to the typescript constructor, the object simply was not loaded in the DOM, therefore it could not be manipulated. Moderators please feel free to remove this question.

Rules to be followed to get window.external work

I found one thing in javascript of my WPF project. It has called
window.external.ShowWindow();
I have found that method is written in class InteropClass like below.
[ComVisible(true)]
public class InteropClass
{
public void ShowWindow()
{
// logic
}
}
and that method is called.
I am trying to analyse it, for that I have used already built class like below
[ComVisible(true)]
public partial class AnotherClass : SomeDifferentClass
{
public void AnotherMethod()
{
// logic
}
}
and tried to call it as
window.external.AnotherMethod();
but it is not working. Error alert says AnotherMethod is not supported by window.external object
I know both classes differs in many terms and I can make it work but my question is What rules to be followed to make this work, may be like class must be directly inherited from Object or some other.
What you need to do is set the ObjectForScripting property on the web
browser control to an object containing the C# methods you want to
call from JavaScript.
from here told me everything I was missing.

$http.post and TypeScript accessors

I am writing an AngularJS app (v1.3.15) using TypeScript 1.5 in Visual Studio 2013. I have run across a problem with TypeScript object properties/accessors and JSON serialization using $http.post(). My AngularJS is pretty solid I think but I am quite new to TypeScript.
My TypeScript class looks like this:
module Wizard.Models {
import Address = Wizard.Models.Address;
"use strict";
export class YourDetailsModel {
public useSecondaryAsPrimary: boolean;
private _primaryFirstName: string;
private _primaryLastName: string;
private _primaryAddressModel: Address = new Models.Address();
get primaryFirstName(): string {
return !this.useSecondaryAsPrimary ? this._primaryFirstName : this.SecondaryFirstName;
}
set primaryFirstName(primaryFirstName: string) {
this._primaryFirstName = primaryFirstName;
}
get primaryLastName(): string {
return !this.useSecondaryAsPrimary ? this._primaryLastName : this.SecondaryLastName;
}
set primaryLastName(primaryLastName: string) {
this._primaryLastName = primaryLastName;
}
get primaryAddressModel(): Address {
return !this.useSecondaryAsPrimary ? this._primaryAddressModel : this.SecondaryAddressModel;
}
set primaryAddressModel(primaryAddressModel: Address) {
this._primaryAddressModel = primaryAddressModel;
}
public SecondaryFirstName: string;
public SecondaryLastName: string;
public SecondaryAddressModel: Address = new Models.Address();
}
}
My intention is that when the object is serialized, all the public members and properties via accessors should be serialized, and the private properties should not. The current behaviour is that some of the private members are being serialized whereas some of the public members are not.
Is this asking too much? There are other ways for me to achieve this so it's not the end of the world if I can't get it working. I don't actually need to fiddle with the model class in this way.
But it's the most elegant way of keeping the model playing its cards close to its chest, so to speak.
Any help appreciated. M.
Is this asking too much? There are other ways for me to achieve this so it's not the end of the world if I can't get it working. I don't actually need to fiddle with the model class in this way
There is no runtime difference between a private and a public member. That is to say that the JavaScript emitted for each is exactly the same.
I suggest using a variable naming convention on top of private/public e.g. public foo and private _foo. Then during serialization you can check if a property name starts with _.

Javascript Variable Value Get From ManagedBean Property

I have a ManagedBean with a property which gets its value from an EJB. In the JSF, I have a Javascript variable which then gets its value from the ManagedBean property. When I run the project, the Javascript variable is not set.
In the ManagedBean, I tried the below methods but doesn't work:
setting the property's value in the Constructor
setting the property's value in an init() method with the #PostConstruct annotation
setting it in the getMenuData() method.
JSF JavaScript
<script>
YAHOO.util.Event.onDOMReady(function ()) {
// Data to build the menubar
var menuData = [#{userMenu.menuData}];
...
});
</script>
ManagedBean
package com.qrra.PROFIT.web;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import qrcom.profit.ejb.UserMenuFacade;
#ManagedBean
#ViewScoped
public class UserMenuController {
public UserMenuController() {
menuData = usermenu.buildMenuDataByUserProfile("UAT");
}
// #PostConstruct
// public void init() {
// menuData = usermenu.buildMenuDataByUserProfile("UAT");
// }
public void getMenuData() {
return this.menuData;
}
public void setMenuData(String menuData) {
// usermenu.buildMenuDataByUserProfile("UAT");
this.menuData = menuData;
}
private String menuData;
#EJB
private UserMenuFacade usermenu;
}
When I view source, I only see var menuData = [];
Is there a workaround to this?
The constructor approach would fail because it's impossible to inject an EJB in the instance before the instance is constructed, you'd only face a NullPointerException as the EJB is null. The #PostConstruct approach should work fine. The business-logic-in-getter approach will also work fine, but it is plain bad design.
Provided that you're properly preforming the job in the #PostConstruct, your code looks fine. Your concrete problem suggests that usermenu.buildMenuDataByUserProfile("UAT"); just returns an empty string by itself and thus your concrete problem needs to be solved at higher level. You should already have determined it by yourself with help of a debugger and common sense.

Categories