Comments (27)
@adrienbaron I don’t see much benefits in boxed types, so your proposal is absolutely good to me. The only concern is what value I’ll get in case of :important=“” ? And in case it’s not defined at all ?
from vue-gwt.
@adrienbaron yes, I like it that way!
from vue-gwt.
The only thing is wrapped primitives Props will make your components non compatible with JS apps, but maybe we can find a way around that in some next release 😉. Thank you for the help!
from vue-gwt.
@adrienbaron Thank you for vue-gwt and quick responses!
from vue-gwt.
@adrienbaron Sure, will open in the morning, it’s deep night in my town.
from vue-gwt.
Hi!
I've just checked, and for this library you don't even need the @JsComponent
annotation. This annotation is useful if you need to extend or access the instance of the JsComponent (which is not the case with Bootstrap).
So all you need to do is include Bootstrap like you did:
<!-- Add this to <head> -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap@next/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css"/>
<!-- Vue JS Framework -->
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<!-- Add this after vue.js -->
<script src="//unpkg.com/babel-polyfill@latest/dist/polyfill.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>
Then in you components you should be able to use bootstrap components directly:
<div>
<b-progress :value="(int) 12" :max="(int) 100" show-progress animated></b-progress>
</div>
In this case we cast the value to int, otherwise it gets casted to Integer.
For your case, it might not work because you are binding variant to "warning", it should probably be:
<b-button variant="warning"></b-button>
from vue-gwt.
@adrienbaron Thank you! It was just silly mistake with binding :-( Unfortunately error message was absolutely not helpful, so I've started to dig in a wrong direction.
from vue-gwt.
@adrienbaron But anyway, question is kind of remains. How to use JsComponent annotation in such case, for example I want to extend b-button somehow. Probably it's incorrect question, because b-button is stateless (functional: true) component, i.e. realistically just a render function.
What I'm trying to do:
@JsComponent("b-button") // or bButton, or something else?
@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") // or "Function" ?
public class BButton extends VueComponent {
}
@Component(hasTemplate = false)
public class MyButton extends BButton {
// here comes extended functionality
}
Then in template:
<my-button>Test</my-button>
from vue-gwt.
Unfortunately error message was absolutely not helpful, so I've started to dig in a wrong direction.
What was the error message? Maybe we can improve it if it's on Vue GWT side.
How to use JsComponent annotation in such case, for example I want to extend b-button somehow
Usually, you should pass your Component constructor or options object to @JsComponent
.
In the case of Vue Bootstrap this is a little tricky to do. They don't expose the Components on an object on Window for you.
However, it's still doable, if you expose them manually. In your index.html, after Bootstrap inclusion add for example:
<script>
window.BootstrapVue = {
bButton: Vue.component("bButton") // Returns a Component Constructor function
}
</script>
Then with this should work just fine:
@JsComponent("BootstrapVue.bButton")
@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Function")
public class BButton extends VueComponent {
}
@Component(hasTemplate = false)
public class MyButton extends BButton {
// here comes extended functionality
}
from vue-gwt.
@adrienbaron Actually, if I don't have invalid BButton class at all, then error message is perfectly fine:
Couldn't find variable/method "secondary" in the Component.
Make sure you didn't forget the @JsProperty/@JsMethod annotation or try rerunning your Annotation processor.
In expression: secondary
While processing Node: <b-button :variant="secondary">
Test
</b-button>
But in case I have invalid BButton class and mentioned it in Component components (actually it fails even in case of proper BButton class declared with "BootstrapVue.bButton"):
@Component(components = { BButton.class })
public class TestComponent extends VueComponent { }
then error:
Breaking on exception: Error: java.lang.RuntimeException: Couldn't find VueFactory for Component: com.axellience.vuegwtdemo.client.components.vx.TestComponent. Make sure that annotation are being processed, and that you added the -generateJsInteropExports flag to GWT. You can also try a "mvn clean" on your maven project.
which gives me nothing useful.
Thank you for advicing window.BootstrapVue = { ... }
works perfectly fine for me.
from vue-gwt.
@adrienbaron I'm sorry for being troublesome, but one more related question. According to docs "Functional Components" are not yet supported, but in this particular case I want to add additional properties to MyButton and adjust render() function, i.e. I want to execute my render code plus call predecessor's render() with probably adjusted properties (for example MyButton has new "important" property, which means size="lg" and variant="warning" for predecessor). I cannot find any meaningful example how to solve such case even on "pure" Vue.
from vue-gwt.
But in case I have invalid BButton class and mentioned it in Component components, then error
Yes, this is kind of a "generic" error in case it can't find the generated component class at Runtime. It can have a lot of causes, from Annotation Processor not running, to missing the JsInterop flag. It can also come from classes that threw error(s) at instantiation and didn't register themselves (which is probably the case here). I'll check exactly what's happening in that case see if I can figure out a better error message.
but in this particular case I want to add additional properties to MyButton and adjust render() function, i.e. I want to execute my render code plus call predecessor's render() with probably adjusted properties (for example MyButton has new "important" property, which means size="lg" and variant="warning" for predecessor).
In that case you wouldn't extend the Component, you would do something like:
@Component
public class MyButton {
@Prop
@JsProperty
boolean important;
@Computed
public String getVariant() {
return important ? "warning" : "info";
}
@Computed
public String getSize() {
return important ? "lg" : "sm";
}
}
With the following template:
<b-button :size="size" :variant="variant"></b-button>
And to use the button:
<my-button :important="(boolean) true"></my-button>
Composition rather than inheritance 😉
from vue-gwt.
@adrienbaron Yes, composition is possible solution, BUT:
- MyButton won't be "functional component" anymore, i.e. it will be "heavier".
- Imagine that b-button has 20 properties, and most of them are needed for MyButton as well, so I have to redeclare all of them, that's really bad.
from vue-gwt.
- If we add support for functional components, you'll be able to declare a render function for your functional component that returns a vNode of your bButton. It will still be a little heavier than the bButton alone (would render 2 functional components instead of 1), but would be better.
- Yes it's sadly the case. On the other end it's bad practice to have too much properties on a Component.
from vue-gwt.
- By the way, not sure if it's a good idea, but perhaps then I can modify/adjust bButton.vNode in my MyButton render function?
- Looks like inheritance is the second class functionality in Vue, first class is composition, that's sad.
from vue-gwt.
- I don't think Vue.js allows overriding a render function. When you extend, if you have a render function, it overrides the original one from what I know.
- Yes, let's not start a debate on inheritance VS composition ;), but I think its more adapted in the case of Components. I mostly use inheritance in Vue GWT projects to expose GWT resources in all my Components for example.
from vue-gwt.
@adrienbaron
By the way, I don't understand @prop generation for boolean.
@Prop @JsProperty boolean important; // generates: options.addJavaProp("important", false, null);
Why jsTypeName is null?
Why in VueComponentOptions.addJavaProp() processing for jsTypeName param is commented out?
IMO it's more natural to write:
<my-button important="true"></my-button>
<!-- instead of: -->
<my-button :important="(boolean) true"></my-button>
from vue-gwt.
jsType is not null if you pass checkType=true
to @Prop
(and the type is determined from the Java type).
But indeed the part in addJavaProp
should not be commented out. From what I see on GitHub history, it's a bug left from the latest beta when we migrated to Elemental. We will fix this for the next beta.
Sadly, even if we pass the type of the prop to Vue, it won't parse it automatically from what I understand:
vuejs/vue#2168
So the binding is mandatory. I was thinking for "simple" value to detect the type (like integer, true/false), to remove the need for casting as it would work in most case. The problem is that for more complex expression (method calls etc...), we won't be able to detect the type and casting would be necessary. Seems "odd" to need casting sometimes and sometimes not.
from vue-gwt.
@adrienbaron Actually it could be possible to add heuristic converter under the hood, and process obvious cases only, like true/false, 123, 456.07 If case is not obvious then casting is mandatory and heuristic is automatically doing nothing.
from vue-gwt.
Yes that's a little what I had in mind, but I actually thought of something better (in my opinion).
If we forbid to used wrapped primitive as props, then we can always just pass the value along as a non wrapped primitive type (think I have a solution for that), and it would just work.
So to sum up you could do:
@JsProperty @Prop boolean important;
<my-button :important="true"></my-button>
<my-button :important="bob > 10"></my-button>
<my-button :important="methodReturningNonWrappedBoolean()"></my-button>
<my-button :important="(boolean) methodReturningWrappedBoolean()"></my-button>
But this would throw an annotation processing error with an explicit message saying wrapped primitive are not supported as @Prop
:
@JsProperty @Prop Boolean important;
What do you think?
from vue-gwt.
I think that will just throw a compilation error, the expression in "" must be always be a valid Java expression. We use https://github.com/javaparser/javaparser to parse it.
from vue-gwt.
@adrienbaron Good. Also in case of numerical types it could be kind of important to distinguish between not defined, i.e. null in case of boxed types, but for primitive types it will be 0 (though js hasProperty may help in such cases)
from vue-gwt.
@slavap Arh yes, that's true didn't think about null. hasProperty
sadly wouldn't work as Vue defines the Props on the object even if they don't have value (if i'm not mistaken).
We could also allow wrapped primitive and force casting in those case:
@JsProperty @Prop Integer counter;
<my-button :counter="(Integer) 10"></my-button>
<my-button :counter="(Integer) 10 + 25"></my-button>
<my-button :counter="(Integer) methodReturningNonWrappedInteger()"></my-button>
<my-button :counter="methodReturningWrappedInteger()"></my-button>
<my-button :counter="null"></my-button>
Might make more sense this way for primitives. Casting would still not be required for non wrapped primitives.
from vue-gwt.
@adrienbaron It works. The only minor problem is:
:important="" gives uninformative error "SyntaxError: Unexpected token ,"
Uncaught SyntaxError: Unexpected token ,
at new Function (<anonymous>)
at $initRenderFunctions_0_g$ (VueComponentOptions.java:109)
at $setComponentTemplate_0_g$ (VueComponentOptions.java:75)
at getOptions_5_g$ (MyButtonJsType.java:30)
at MyButtonFactory_1_g$.init_15_g$ [as init_12_g$] (MyButtonFactory.java:27)
at get_83_g$ (MyButtonFactory.java:37)
at lambda$1_33_g$ (MyButtonJsType.java:15)
at MyButtonJsType$lambda$1$Type_1_g$.get_85_g$ [as get_72_g$] (MyButtonJsType.java:15)
at getFactory_1_g$ (VueGWT.java:112)
at getFactory_0_g$ (VueGWT.java:100)
at new VueGwtWidget_3_g$ (VueGwtWidget.java:35)
from vue-gwt.
@slavap The part between quotes must be a java expression, so if you type :important=""
it's like you are typing:
this.important = ;
Which is not valid java. You can either not bind: important=""
, which would just pass an empty string, or bind the empty string value: :important='""'
from vue-gwt.
@adrienbaron I was just experimenting with intentionally wrong template. It’s quite easy to miss value between quotes.
from vue-gwt.
@slavap Ah sorry, I read to fast. Yes I should cast this exception and add a more informative message with the attribute and node responsible for the error. Can you open a new issue for this?
from vue-gwt.
Related Issues (20)
- Use vue-gwt to develop eclipse plugin HOT 1
- Demo Project is busted HOT 8
- Example of using an existing VueJS component library HOT 1
- Vue-GWT plugin not supported in Intellij 2021.1 HOT 1
- vue-gwt admin project demo HOT 1
- Integration tests break on Windows because of line breaks HOT 1
- Add static import support in templates
- Add SASS/SCSS support for scoped styles.
- Works with Gradle instead of Maven? HOT 13
- Improve with a more explicit error in the case of absence of jsinterop exports
- Cannot compile war file from IntelliJ HOT 5
- Implicit boolean value in HTML template HOT 2
- CSS Speudo class problem
- Support .sync Modifier HOT 1
- cannot integrate with compilation problems HOT 1
- how to run ‘Your First Component # Simple Link Component’ HOT 1
- Catch events from JS in Java HOT 8
- Replace Nashorn HOT 7
- Is it possible to parse a .vue file using this project HOT 1
- vue-next support HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from vue-gwt.