npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-meteor-tracker

v2.0.0

Published

Use Meteor Tracker reactivity inside Vue components

Downloads

10,117

Readme

Vue integration for Meteor

npm npm vue3 vue2.7

Reactive subscriptions and data from Meteor for Vue components.

Sponsors

Become a sponsor!

We are very grateful to all our sponsors for their support:

Installation

meteor npm install --save vue-meteor-tracker@next

Install vite:bundler too:

meteor add vite:bundler

Learn more

Example Vite config:

import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [
    Vue(),
  ],

  optimizeDeps: {
    exclude: [
      'vue-meteor-tracker',
    ],
  },

  meteor: {
    clientEntry: 'imports/ui/main.ts',
  },
})

Options API

Install the plugin into Vue:

import { VueMeteor } from 'vue-meteor-tracker'
app.use(VueMeteor)

In your Vue component, add a meteor object :

export default {
  meteor: {
    // Meteor specific options
  }
}

Subscriptions

Add an object for each subscription in a $subscribe object. The object key is the name of the publication and the value is either an array of parameters or a function returning an array of parameters. These subscription will be stopped when the component is destroyed.

export default {
  meteor: {
    // Subscriptions
    $subscribe: {
      // Subscribes to the 'threads' publication with no parameters
      'threads': [],
      // Subscribes to the 'threads' publication with static parameters
      'threads': ['new', 10], // The 10 newest threads
      // Subscribes to the 'posts' publication with dynamic parameters
      // The subscription will be re-called when a vue reactive property changes
      'posts': function() {
        // Here you can use Vue reactive properties
        return [this.selectedThreadId] // Subscription params
      }
    }
  }
}

You can also use the $subscribe(name, params) method in you component code:

mounted () {
  // Subscribes to the 'threads' publication with two parameters
  this.$subscribe('thread', ['new', 10])
}

The $subReady object on your component contains the state of your subscriptions. For example, to know if the 'thread' subscription is ready, use this reactive expression:

console.log(this.$subReady.thread)

Or in your template:

<div v-if="!$subReady.thread">Loading...</div>

You can also change the default subscription method by defining the Vue.config.meteor.subscribe function:

import { config } from 'vue-meteor-tracker'

// You can replace the default subcription function with your own
// Here we replace the native subscribe() with a cached one
// with the ccorcos:subs-cache package
const subsCache = new SubsCache({
  expireAfter: 15,
  cacheLimit: -1
})

config.subscribe = function(...args) {
  return subsCache.subscribe(...args)
}

Reactive data

You can add reactive properties that update from any Meteor reactive sources (like collections or session) by putting an object for each property in the meteor object. The object key is the name of the property (it shouldn't start with $), and the value is a function that returns the result.

Here is an example:

export default {
  data() {
    return {
      selectedThreadId: null
    }
  },
  meteor: {
    // Subscriptions
    $subscribe: {
      // We subscribe to the 'threads' publication
      'threads': []
    },
    // Threads list
    // You can access tthe result with the 'threads' property on the Vue instance
    threads () {
      // Here you can use Meteor reactive sources
      // like cursors or reactive vars
      // as you would in a Blaze template helper
      return Threads.find({}, {
        sort: {date: -1}
      })
    },
    // Selected thread
    selectedThread () {
      // You can also use Vue reactive data inside
      return Threads.findOne(this.selectedThreadId)
    }
  }
})

Use the reactive data in the template:

<!-- Thread list -->
<ThradItem
  v-for="thread in threads"
  :data="thread"
  :selected="thread._id === selectedThreadId"
  @select="selectThread(thread._id)"
/>

<!-- Selected thread -->
<Thread v-if="selectedThread" :id="selectedThreadId"/>

Or anywhere else in you Vue component:

computed: {
  count () {
    return this.threads.length
  }
}

Meteor Methods

You can call a Meteor method with a promise using callMethod:

import { callMethod } from 'vue-meteor-tracker'

export default {
  methods: {
    async insertLink () {
      try {
        await callMethod('links.insert', 'title', 'url')
        console.log('done')
      } catch (e) {
        console.error(e)
      }
    },
  },
}

Composition API

Subscriptions

Inside the component setup, you can use the subscribe function:

import { subscribe } from 'vue-meteor-tracker'

// Simple sub

subscribe('links')
// With params
subscribe('linksByPageAndLimit', 1, 10)

// Reactive sub

const page = ref(1)
subscribe(() => ['linksByPageAndLimit', page.value, 10])

If you need to subscribe later (outside of the setup context), call useSubscribe instead:

import { useSubscribe } from 'vue-meteor-tracker'

const { subscribe } = useSubscribe()

setTimeout(() => {
  subscribe('linksByPage', 2)
}, 1000)

Reactive Data

In the component setup context, you can use the autorun function:

import { autorun } from 'vue-meteor-tracker'
import { LinksCollection } from '/imports/api/links'

const links = autorun(() => LinksCollection.find({}).fetch()).result
// const { result, stop } = autorun(() => LinksCollection.find({}).fetch())

If you need to start an autorun later (outside of the setup context), call useAutorun instead:

import { useAutorun } from 'vue-meteor-tracker'
import { LinksCollection } from '/imports/api/links'

const { autorun } = useAutorun()

// Later...
const links = autorun(() => LinksCollection.find({}).fetch()).result

Meteor Methods

You can call a Meteor method with a promise using callMethod:

import { callMethod } from 'vue-meteor-tracker'

async function insertLink () {
  try {
    await callMethod('links.insert', 'title', 'url')
    console.log('done')
  } catch (e) {
    console.error(e)
  }
}

To keep track of pending, error and result state with reactive variables, you can use useMethod:

import { useMethod } from 'vue-meteor-tracker'
import { LinksCollection } from '/imports/api/links'

const insertLinkMethod = useMethod<[url: string, link: string]>('links.insert')
insertLinkMethod.onResult((err) => {
  if (!err) {
    // Reset form
    insertLinkForm.title = ''
    insertLinkForm.url = ''
  }
})

// Reactive state
watch(insertLinkMethod.pending, () => { /* ... */ })
watch(insertLinkMethod.error, () => { /* ... */ })
watch(insertLinkMethod.result, () => { /* ... */ })

const insertLinkForm = reactive({
  title: '',
  url: '',
})

async function insertLink () {
  await insertLinkMethod.call(insertLinkForm.title, insertLinkForm.url)
  console.log('done')
}

License

MIT