Git Product home page Git Product logo

Comments (27)

slavap avatar slavap commented on May 30, 2024 1

@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.

slavap avatar slavap commented on May 30, 2024 1

@adrienbaron yes, I like it that way!

from vue-gwt.

adrienbaron avatar adrienbaron commented on May 30, 2024 1

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.

slavap avatar slavap commented on May 30, 2024 1

@adrienbaron Thank you for vue-gwt and quick responses!

from vue-gwt.

slavap avatar slavap commented on May 30, 2024 1

@adrienbaron Sure, will open in the morning, it’s deep night in my town.

from vue-gwt.

adrienbaron avatar adrienbaron commented on May 30, 2024

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.

slavap avatar slavap commented on May 30, 2024

@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.

slavap avatar slavap commented on May 30, 2024

@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.

adrienbaron avatar adrienbaron commented on May 30, 2024

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.

slavap avatar slavap commented on May 30, 2024

@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.

slavap avatar slavap commented on May 30, 2024

@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.

adrienbaron avatar adrienbaron commented on May 30, 2024

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.

slavap avatar slavap commented on May 30, 2024

@adrienbaron Yes, composition is possible solution, BUT:

  1. MyButton won't be "functional component" anymore, i.e. it will be "heavier".
  2. 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.

adrienbaron avatar adrienbaron commented on May 30, 2024

@slavap

  1. 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.
  2. 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.

slavap avatar slavap commented on May 30, 2024

@adrienbaron

  1. 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?
  2. Looks like inheritance is the second class functionality in Vue, first class is composition, that's sad.

from vue-gwt.

adrienbaron avatar adrienbaron commented on May 30, 2024

@slavap

  1. 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.
  2. 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.

slavap avatar slavap commented on May 30, 2024

@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.

adrienbaron avatar adrienbaron commented on May 30, 2024

@slavap

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.

slavap avatar slavap commented on May 30, 2024

@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.

adrienbaron avatar adrienbaron commented on May 30, 2024

@slavap

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.

adrienbaron avatar adrienbaron commented on May 30, 2024

@slavap

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.

slavap avatar slavap commented on May 30, 2024

@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.

adrienbaron avatar adrienbaron commented on May 30, 2024

@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.

slavap avatar slavap commented on May 30, 2024

@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.

adrienbaron avatar adrienbaron commented on May 30, 2024

@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.

slavap avatar slavap commented on May 30, 2024

@adrienbaron I was just experimenting with intentionally wrong template. It’s quite easy to miss value between quotes.

from vue-gwt.

adrienbaron avatar adrienbaron commented on May 30, 2024

@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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.