0.3.0 • Published 3 years ago

vue-elm-components v0.3.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

vue-elm-components

Simply embed Elm apps as components into your Vue.js applications

This package makes it easy to turn Elm code into Vue.js components.

Companies that use Elm in production usually start small. Read more about how to use Elm at work here.

Development Status

  • Immediate Goals
    • Add demos for Elm 0.18 and 0.19
    • Add automated tests
  • Coming Soon
    • Interact with Elm ports using Vue.js props and events

Usage

Installation

npm i vue-elm-components

Basic Usage

If you have an Elm app, you can import it using the elm-webpack-loader and embed it in your Vue code like this:

<template>
  <v-elm :src="Counter" />
</template>

<script>
import VElm from 'vue-elm-components'

import Counter from '@/path/to/file/Counter.elm'

export default {
  data: { Counter },
  components: { VElm }
}
</script>

Flags

Sometimes you want to give your Elm program some flags on start up. Let's say we want our counter to start at 5. You would write something like this:

<template>
  <v-elm
    :src="Counter"
    :flags="flags"
  />
</template>

<script>
import VElm from 'vue-elm-components'

import Counter from '@/path/to/file/Counter.elm'

export default {
  data: {
    Counter,
    flags: { start: 5 }
  },
  components: { VElm }
}
</script>

These flags will be given to the Elm program, allowing you to do some setup work in your Vue code first.

JavaScript/Elm Interop

As your Elm program gets fancier, you will probably need to interact with JavaScript. We do this with ports. Think of these as holes in the side of an Elm program that let you pass messages back-and-forth.

So let's say we want to extend our app to allow outsiders to modify the counter through the counter port. And maybe we also expose the current count so that outsiders can subscribe to it using the countChanged port. You would set it up like this:

<template>
  <v-elm
    :src="Counter"
    :ports="setupPorts"
  />
</template>

<script>
import VElm from 'vue-elm-components'

import Counter from '@/path/to/file/Counter.elm'

export default {
  data: {
    Counter,
    currentCount: 0,
  },
  methods: {
    setupPorts(ports) {
      ports.countChanged.subscribe((n) => {
        this.currentCount = n;
      });
      ports.counter.send(1);
      ports.counter.send(1);
    }
  },
  components: { VElm }
}
</script>

Advanced Usage

Once the Elm component is initialized, changing the flags and ports properties will do nothing. So here are some tricks that may help you out:

  1. If you want to reinitialize your Elm component, add a different key to the old and new components. This way old one is destroyed and replaced by the new one.
  2. This package is super simple. Check out the implementation and do it different if you want!
  3. You can also use compiled versions of your elm app (.js outputs) if you find it easier.
  4. The default export from an Elm module (.elm or compiled to .js) is an object which contains your app as a property. For example, you can imagine that a file named Counter.elm, or its compiled counterpart named dist/counter.js will export something like this:
export default {
  Elm: {
    Main: {
      embed: [[Function]], // version 0.18 and prior
      init:  [[Function]], // since version 0.19
    }
  }
}

Angular, Ember, etc.

If you want to embed Elm in something else, you are in luck!

The implementation is pretty short, mostly Vue-related. The important lines are basically running the following program at the correct time:

import App from "@/path/to/file/App.elm";
var app = App.Elm.Main.embed(node, flags);
setupPorts(app.ports)

So if you are interested in embedding Elm in something else, do the same trick! You can get more complete docs on embedding Elm in JS here. Let the community know if you make something!


This package was inspired by react-elm-components which is maintained by the good folks at Culture Amp.

0.3.0

3 years ago

0.2.0

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago