Basics: Component building in Meteor + VueJS

I’m building a Meteor + VueJS form. When building forms, I like to build each control, input, dropdown/select, radio, as a “component”. In the case of Blaze, this would be analogous to a small template, where I pass in data from a parent template. But I’m not positive how this is done in VueJS.

Also, in most forms we use type checking, validation, and default values. At the moment I’m using SimpleSchema for this, but saw there might be an alternative with VueJS 2.0 here: https://vuejs.org/v2/api/#props & https://vuejs.org/v2/guide/components.html#Props. It would be nice to factor out SimpleSchema for a VueJS API call. In fact, I’d like to use only the VueJS 2.0 API if for all my form needs if possible.

Can someone point me to examples of this scenario in VueJS 2.0?

1 Like

I prefer using SimpleSchema cause I’m already using it to manage the data on the server anyways.

In Blaze, there’s a great help for form components - “ref” feature of manuel:viewmodel package, which provides comfortable child->parent communication perfect for use in case of form elements, where parent component manages the state and child component renders the element. Same with parent component managing the hole form and children element components.

In Vue2, ref is not reactive anymore so can’t be used the same way, but that may change in future versions.

Sure. With ref in Blaze, you can do something like that:

+childTemplate(ref="inputValue")

and then in javascript, use the value of input element from childTemplate as this.inputValue

It seems Vue had same feature and it may come back in the future, check this issue: https://github.com/vuejs/vue/issues/3842

----

I took a look at your examples in a while when I'm free and provide some tips. But did you try to write the props yourself? I don't see them in your code.

It's all possible to achieve, but the list of validation features you wanted is pretty long, so I'll just point you in good direction and you can write the rules you wish to have.

[quote="aadams, post:3, topic:32731"]
Also, I'd like the first name field to be filled out before the second input (last name is visible)
[/quote]
It would be a pain for users who don't fill the forms in regular order. There are such people, I'm one of them and if I noticed such an user unfriendly behavior in sign up form, I'd just switch to the other tab with the website of your competitor, because I could expect similar thing in the forms inside your app.
1 Like

Sorry, these are not REAL requirements, these are various form states that could happen under different circumstances. I’m trying to combine a bunch of these conditions into just two or three controls – so I improvised. Basically I’d like to understand how to show and hide a input control based on another input control’s value, or enabled/disabled a control based on another input controls state. I’d sometimes need to do date calculations in a function, or checkbox states, or radio button states, or a value inside a input control to show/hide, enable/disable other controls.

1 Like

Glad to hear that. :slight_smile: Example is in the making.

1 Like

I’ve figured out basic component building – works great, and so easy to pick up and use. And the component building experience is amazing. Coming from Blaze, Vue just makes sense. But this is only parent to child and child to parent communication. Now I’m going to need sibling component-to-component communication too.

It looks like I’m going to need state-management for more than trivial scenarios, https://vuejs.org/v2/guide/state-management.html. From the article:

Large applications can often grow in complexity, due to multiple pieces of state scattered across many components and the interactions between them. To solve this problem, Vue offers vuex: our own Elm-inspired state management library. It even integrates into vue-devtools, providing zero-setup access to time travel.

Has anyone use Vuex (akryum:vuex) for sibling component communication with Meteor? This repo https://github.com/Akryum/meteor-vuex-example has examples using Vue 1.0, can they be used with Vue 2.0?

For example, a checkbox control and a text input on the same template, the checkbox control needs to be in the true state for the text input to become visible and editable. So once the checkbox control is checked, I’m guessing it emits it’s state, and the input control will listen.

Also, just thinking here, will the input control even be available to listen if it’s not visible? In blaze I have a helper method that checks for state and shows/hides controls on an #if statement.

Vuex is actually pretty simple, fun to use and gives awesome stuff like the mentioned time travel. A simple example of how you can use Vue2 in Meteor is in my Vuex-Accounts example project, even if it is much more verbose than pure Vue. Of course you won’t be able to use specific features that Akryum provided for his Vuex1 package, which let you to make your subscriptions directly in Vuex and keep collections reactive there without having to setup anything, but it’s easy to do at the template level, like how we recently do that with Meteor+FlowRouter.

Overall, I’d say Vue (with Vuex or not) is more comfortable to handle than Blaze, but less comfortable than Blaze+ViewModel.

Answering your question, yes - somewhere on github issues Akryum stated that Meteor+Vuex goodies from his Vuex1 package won’t work with Vue2. The Vuex2 package is a part of RC roadmap.

But for a simple state management in a small app you don’t even need Vuex. All you need is a Store object if you don’t want to use migrations/getters/actions/whatever but simply use and update the State directly.

Still I’d go with Vuex so you can understand how it works on a small app first.

Now for the simplest Vuex sibling communication. Let’s use your checkbox/input example. Remember to pass the store to the main component if you want it available by default in all children this way:

/imports/ui/app.js

export default {
  store
}

/imports/vuex/store.js <- the export.default part here depends on how you initialize the store, as there are at least two options. One is described in my Vuex-Accounts example, the one below is a part of how I do it usually, because it works nice with vuex-router-sync. So first you have to actually initialize Vuex in your app, you’ll find the details in docs.

export default({
  state: {
      checkbox: false
  },
    mutations: {
        updateCheckbox(state, payload) {
            state.checkbox = payload
        }
    }
})

/imports/ui/checkbox.vue - here we need to make sure v-model on checkbox both updates the store and gets updated by the store, that’s why we’ll use a computed getter and setter. It is more verbose than simple v-model but it will be needed if we use Vuex’s strict mode in which the state can only be updated in the store (and which is I believe the default store behavior in Redux?).

<template>
  <checkbox v-model="checkbox">
</template>

<script>
export default {
  computed: {
    checkbox() {
      get() {
        return this.$store.state.checkbox
      },
      set(value) {
        this.$store.commit('updateCheckbox', value)
      }
    }
  }
}
</script>

/imports/ui/input

<template>
  <input :disabled="$store.state.checkbox" />
</template>

or if we don’t want to use state directly in templates:

<template>
  <input :disabled="checkbox" />
</template>
<script>
export default {
  computed: {
    checkbox() {
      return this.$store.state.checkbox
    }
  }
}
</script>

All of that is explained in Vuex docs of course.

2 Likes

As for form validation management, I promised an example, but when I was working on it, I discovered a brilliant Vee-Validate package http://vee-validate.logaretm.com, so now I’m working on the way to make Vee-Validate working with Simple Schema, cause that would be a huge step in the right direction. Sorry for no code yet.

Would you care to explain the reasons for your feeling more comfy with ViewModel than with Vue?
I am curious because I am currently evaluating three UI component packages for a meteor app:

  • akryum:vue-app
  • manuel:viewmodel
  • peerlibrary:blaze-components

After just reading the tutorials and docs, it seems that Vue is much more comprehensive in terms of component modeling requirements variety, while allowing for gradual adoption of the most advanced features. It is also supposed to follow a design that is more scalable in terms of performance.

In addition, the fact that there is a Vue Chrome Devtool extension and such comprehensive documentation and free online video tutorials is making me leaning towards Vue.

So could you elaborate on what are the weaknesses of Vue as compared to ViewModel that you have experienced in terms of productivity, learning curve and overall user experience?

Sure. But first, two things have to be addressed.

First of all, I’m simply more used to Manuel’s package and I don’t know yet all the secrets behind Vue. Secondly, by “more comfortable” I didn’t mean the whole coding experience, but just the ease and fun of writing code.

Vue vs Viewmodel is kinda “PC vs console for gaming” decision. Both have their advantages (and ultimately PC will always be better :wink: ).

You are right that one of the best things about Vue is that it allows for gradual adoption of features. We can write a fine application without touching half of the stuff Vue provides. I love it about Vue.

But even if you compare the basic, shortest and fastest to prototype with version of Vue, Blaze+Viewmodel will still let you achieve more with shorter syntax and less complex code with almost no boilerplate. With Viewmodel, writing the code and managing the state is just so uncomplicated that it’s pure fun and unlike pure Blaze, it’s very easy to tell what’s going on where even after a longer break.

You know why there are no tutorials and extensive documentation for manuel:viewmodel? Because it’s not needed. It just works.

On the other hand, Vue shows its claws when you actually prefer to get more complex, f.e. when you wish to use Vuex in place of Viewmodel’s simple state management. Vue devtools are great too, especially with Vuex time travel feature. What I also find definitely an advantage of Vue vs Blaze is dealing with issues. Vue console warnings and error messages system is simply awesome.

As you want to make a good choice, I’d say this: if you for some reason want Blaze, do yourself a favor and go with Viewmodel.

But at the higher level of discussion, if you have a choice between Blaze and Vue, just go with Vue and forget about Blaze, for reasons such as hot module reload, time travel, native mobile UI and others, and because Vue has a future, while in the current state, Blaze only may have a future - in this context it’s a safer choice.

That said, you will lose Blaze’s advantage of being able to use Meteor-related packages like Autoform, which make development way faster. And there are no alternatives in Vue ecosystem.

The third option would be manuel:viewmodel package in its React flavour. It actually sounds very cool. But as I have no experience with that, I can’t talk about it.

1 Like

Thanks for that @gusto. But I’d rather not use SimpleSchmea as the Vue API seems to handle validation just fine – and I’d like to hand the validation within the component itself, passing into what it needs to make the right decisions, instead of a monolithic SimpleSchema data structure.

Of course we do get the additional server side checking & validation with SimpleSchema – so there’s that I suppose.

Why can’t we npm install vuex directly and use it without akryum’s vuex package? That’s the problem with wrappers like this, when there’s an update, sometimes we have an uncertain upgrade path. From what I’ve read vuex2 has a much cleaner, less verbose syntax (no more getters/setters for example).

You don’t need to use akyrum’s packages and I would advise against them actually since they’re not just a simple wrapper around the Vue libraries and they will eventually get out of date. For instance the akyrum:vuex package actually adds an additional layer on top of the Vuex api, which will just be more confusing if you’re already familiar with Vuex. Instead you should just use the vuex package right from npm. The only package you’ll really need is the akyrum:vue-component build plugin that builds .vue component files with hot-reload, and if you’re using Tracker data you’ll need a plugin that lets you use reactive Tracker data inside Vue components.

3 Likes

Does anyone want to take a stab at writing a blog post or guide article about Vue.js with Meteor?

It could be quite short to start, just a recommendation of how to install the right packages.

2 Likes

I’d be happy to when I’m finished with some other open source work that takes priority, but that might not be for another few months. So if someone else wants to hop on it, go for it. It seems like there’s been good momentum for Vue around here so it’s about time

2 Likes

[quote=“aadams, post:17, topic:32731”]
Why can’t we npm install vuex directly and use it without akryum’s vuex package?[/quote]
Yes we can, I’m doing just that in my Vuex-Accounts example app.

I have no experience with Vuex1, but I’m not sure the getters were even needed there. Anyways, in Vuex2 getters are available, even if you don’t have to use them. Getters can be sometimes useful when you want to grab part of the state already tweaked by some small function. I’m not using that though.

I’m not sure that’s what @efrancis was reffering to. :wink:

It’s just that he answered your question “do I need Akryum’s Vuex package”. @efrancis is right that 1) you don’t need it to make Vuex work with Meteor, 2) it adds additional layer that lets you to use subscriptions and other Meteor stuff directly in Vuex. For obvious reasons, that’s not something that pure npm Vuex library provides out of the box. This is the missing “Meteor magic” part and sounds pretty cool, but as it’s stuck to Vue1 for now, that’s not an option for me.

So it’s your choice, if you need this thing. At the moment, I’m going with original npm Vuex2, I will most probably change it once Vuex2 package for vue-component is available. But it’s on “nice to have” part of Beta roadmap, so it will take a while.

I’m not really sold yet on the “state only in Vuex” approach, as I lack experience with this kind of state management. It will take some time for me too to fully grasp it and realize its potential. I’m willing to give it a try though.

1 Like

I believe we could start with a few tutorials and articles at places like Medium. Because the best practices… they don’t yet exist imho for Vue+Meteor. It will take a time for discussions and sharing the experience among people who use it.

1 Like

I just made an example in jsFiddle. You can see that I made a form component that hold some data, which is used to enable or disable an input based on the value of another one. Plus, I do simple automatic form validation without plugin.


If you want to remove the akryum:vue package, install vue-meteor-tracker with npm:

npm install --save vue-meteor-tracker

And add this in your app code:

import VueMeteorTracker from 'vue-meteor-tracker'
Vue.use(VueMeteorTracker)

The akryum:vue package is now mostly empty because I moved its content to the npm vue-meteor-tracker package.

3 Likes

@akryum thx, that’s a very nice example.

In your opinion, which way would you recommend as a best practice? To use akryum:vue or to do what you describe above?

That’s not the proper order. :wink: First Vue.use, then new Vue.

1 Like