Skip to content

Instantly share code, notes, and snippets.

@bduisenov
Last active March 18, 2016 11:55
Show Gist options
  • Save bduisenov/2c5ef0e4ff4874f2c5d2 to your computer and use it in GitHub Desktop.
Save bduisenov/2c5ef0e4ff4874f2c5d2 to your computer and use it in GitHub Desktop.
gwt jsinterop mapping to vue.js
import jsinterop.annotations.JsConstructor;
import jsinterop.annotations.JsFunction;
import jsinterop.annotations.JsIgnore;
import jsinterop.annotations.JsMethod;
import jsinterop.annotations.JsOverlay;
import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsProperty;
import jsinterop.annotations.JsType;
import com.google.gwt.dom.client.Element;
/**
* Created by bduisenov on 16/12/15.
*/
@JsType(namespace = JsPackage.GLOBAL, isNative = true)
public class Vue<T> {
@JsProperty
private static Config config;
/**
* The data object for the Vue instance. It can be accessed as vm.$data
*/
@JsProperty
private Data<T> $data;
@JsConstructor
public Vue(Options<T> options) {
}
/**
* Vue.config is an object containing Vue’s global settings. Here are the list of all the
* avaiable settings with their default values
*
* <code>
* {
* // print stack trace for warnings?
* debug: true,
* // attribute prefix for directives
* prefix: 'v-',
* // interpolation delimiters
* // for HTML interpolations, add
* // 1 extra outer-most character.
* delimiters: ['{{', '}}'],
* // suppress warnings?
* silent: false,
* // interpolate mustache bindings?
* interpolate: true,
* // use async updates (for directives & watchers)?
* async: true,
* // allow altering observed Array's prototype chain?
* proto: true
* }
* </code>
*/
@JsType
public static class Config {
public boolean debug = true;
public Config(boolean debug) {
this.debug = debug;
}
}
/**
* The instantiation options used for the current Vue instance. This is useful when you want to
* include custom properties in the options
*
* @param <T>
*/
@JsType
public static class Options<T> {
/**
* Provide the Vue instance with an existing DOM element. It can be a CSS selector string,
* an actual HTMLElement, or a function that returns an HTMLElement. The resolved element
* will be accessible as vm.$el.
*
* When used in Vue.extend, a function must be provided so each instance gets a separately
* created element.
*
* If the option is available at instantiation, the instance will immediately enter
* compilation; otherwise, the user will have to explicitly call vm.$mount() to manually
* start the compilation.
*/
public String el;
/**
* The data object for the Vue instance. It can be accessed as vm.$data
*/
public Data<T> data;
/**
* A string template to be inserted into vm.$el. Any existing markup inside vm.$el will be
* overwritten, unless content insertion points are present in the template. If the replace
* option is true, the template will replace vm.$el entirely.
*
* If it starts with # it will be used as a querySelector and use the selected element’s
* innerHTML and the template string. This allows the use of the common
* <script type="x-template"> trick to include templates.
*/
public String template;
/**
* An object where keys are expressions to watch and values are the corresponding callbacks.
* The value can also be a string of a method name. The Vue instance will call $watch() for
* each entry in the object at instantiation
*
* <code>
* var vm = new Vue({
* data: {
* a: 1
* },
* watch: {
* 'a': function (val, oldVal) {
* console.log('new: %s, old: %s', val, oldVal)
* }
* }
* })
* vm.a = 2 // -> new: 2, old: 1
* </code>
*/
public Watch watch;
@JsIgnore
public Options(String el, Data<T> data) {
this.el = el;
this.data = data;
}
@JsIgnore
public Options(String el, Data<T> data, String template) {
this.el = el;
this.data = data;
this.template = template;
}
@JsIgnore
public Options(String el, Data<T> data, Watch watch) {
this.el = el;
this.data = data;
this.watch = watch;
}
}
@JsType
public static class Data<T> {
public T data;
@JsIgnore
public Data(T data) {
this.data = data;
}
}
@FunctionalInterface
@JsFunction
public interface Function2<T> {
void apply(T newVal, T oldVal);
}
@JsType
public static class Watch {
@JsType
public static class Handler {
Function2 handler;
}
@JsProperty
Handler data;
@JsProperty
boolean deep;
}
@JsOverlay
public final Data<T> get$data() {
return $data;
}
@JsOverlay
public final void set$data(T $data) {
this.$data = new Data<>($data);
}
/**
* Set a data value on the Vue instance given a valid keypath. If the path doesn’t exist it will
* be created.
*/
@JsMethod(name = "$set")
protected native void $setInner(String keypath, T value);
@JsOverlay
public final void $set(String keypath, T value) {
$setInner("data." + keypath, value);
}
@JsOverlay
public final void $set(T value) {
$setInner("data", value);
}
/**
* If the Vue instance didn’t get an el option at instantiation, you can manually call $mount()
* to assign an element to it and start the compilation. If no argument is provided, an empty
* <div> will be automatically created. Calling $mount() on an already mounted instance will
* have no effect. The method returns the instance itself so you can chain other instance
* methods after it.
*/
public native void $mount(Element element);
public native void $mount(String id);
/**
* Completely destroy a vm. Clean up its connections with other existing vms, unbind all its
* directives and remove its $el from the DOM. Also, all $on and $watch listeners will be
* automatically removed.
*/
public native void $destroy();
public native void $destroy(boolean remove);
/**
* Watch an expression on the Vue instance for changes. The expression can be a single keypath
* or actual expressions
*/
public native void $watch(String expression, Function2 callback);
/**
* To also detect nested value changes inside Objects, you need to pass in true for the third
* deep argument. Note that you don’t need to do so to listen for Array mutations.
*/
public native void $watch(String expression, Function2 callback, boolean deep);
/**
* Passing in true for the fourth immediate argument will trigger the callback immediately with
* the current value of the expression
*/
public native void $watch(String expression, Function2 callback, boolean deep, boolean immediate);
@JsOverlay
public static <T> Vue<T> create(String el, T data) {
return new Vue<>(new Options<>(el, new Data<>(data)));
}
@JsOverlay
public static <T> Vue<T> create(String el, T data, Function2 watchHandler) {
final Watch watch = new Watch();
final Watch.Handler handler = new Watch.Handler();
handler.handler = watchHandler;
watch.data = handler;
watch.deep = true;
Vue.config = new Config(true);
return new Vue<>(new Options<>(el, new Data<>(data), watch));
}
@JsOverlay
public static <T> Vue<T> create(Config config, String el, T data, Function2 watchHandler) {
final Watch watch = new Watch();
final Watch.Handler handler = new Watch.Handler();
handler.handler = watchHandler;
watch.data = handler;
watch.deep = true;
return new Vue<>(new Options<>(el, new Data<>(data), watch));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment