Creative Bracket

Vue.js–Get started in Dart (Part 2)

In Part 1 of the series we went through several examples of the Vue.js guide, finishing at Conditionals and Loops.

In this part we will be resuming with the tutorial looking at Handling User Input and Composing With Components.


Handling User Input

In order to attach event listeners that can invoke methods on our Vue instances, we are given the v-on directive to help us handle that.

Provided we have this template in our web/index.html:

<div id="app-5">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">Reverse Message</button>
</div>

The JS counterpart looks like this:

var app5 = new Vue({
  el: '#app-5',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
});

From the solution of Part 1 we are now able to create a Vue instance and set the el and data information. In order for us to be able to define methods, we need to inform our instance of this property.

In web/app.dart, amend the VueOptions anonymous class as follows:

@JS()
@anonymous
class VueOptions {
  external factory VueOptions({
    String el,
    VueDataOptions data,
    VueMethodOptions methods, // <-- Add this line
  });
  external String get el;
  external VueDataOptions get data;
  external VueMethodOptions get methods; // <-- Add this line
}

Next, create the VueMethodOptions factory class in the same file:

@JS()
@anonymous
class VueMethodOptions {
  external factory VueMethodOptions({
    Function reverseMessage,
  });
  external Function get reverseMessage;
}

reverseMessage is the method that is invoked once the button is clicked.

Let’s use what we have so far in web/main.dart to invoke our method:

Vue(VueOptions(
  el: '#app-5',
  data: VueDataOptions(
    message: 'Hello Vue.js',
  ),
  methods: VueMethodOptions(
    reverseMessage: () {
      print('Hello, World!');
    }
  )
));

Run the local server(webdev serve --live-reload) and visit https://creativebracket.com.

Click the button. You should now see “Hello World!” printed to the console.

So what about this bit below?:

this.message = this.message.split('').reverse().join('')

You’ll immediately find that attempting that won’t work, since the Vue context is not inside that function. In order to use a Dart function in JavaScript, we need to use the allowInterop or allowInteropCaptureThis wrapper functions in the inbuilt dart:js library:

// In main.dart
import 'dart:js'; // <-- Import this first
..
..
..
Vue(VueOptions(
  el: '#app-5',
  data: VueDataOptions(
    message: 'Hello Vue.js',
  ),
  methods: VueMethodOptions(
    reverseMessage: allowInteropCaptureThis((gotThis) {
      window.console.dir(gotThis);
    })
  )
));

Here, allowInteropCaptureThis is used not just to use a Dart function in JavaScript, but it also captures the this context and makes it available through the first argument of the function. Therefore, running that logic and clicking the button will print the Vue instance to the console.

You’ll immediately find that doing gotThis.message will give you an error. This is because gotThis is set to a dynamic type by default, and dynamic types do not have a message property.

To resolve we need to cast the argument to the correct type:

// `gotThis` is cast to `Vue`
allowInteropCaptureThis((Vue gotThis) {...});

And inform our factory of the message property:

// In web/app.dart
@JS()
class Vue {
  external factory Vue(VueOptions options);
  external void set seen(bool val);
  external List<Todo> get todos;
  external String get message; // <-- Added this line
  external void set message(String updatedMessage); // <-- Added this line
}

Return to web/main.dart and follow through with the method:

allowInteropCaptureThis((Vue gotThis) {
  gotThis.message = gotThis.message.split('').reversed.toList('').join('');
});

And here we go:

Further reading

  1. js package
  2. How to Use JavaScript libraries in your Dart applications
  3. Learn Full-stack web development with Dart

Sharing is caring 🤗

If you enjoyed reading this post, please share this through the various social buttons hovering on the left/top side of the screen ↖️⬆️. Also, check out and subscribe to my YouTube channel (hit the bell icon too) for videos on Dart.

Subscribe to the newsletter for my free 35-page Get started with Dart eBook and to be notified when new content is released.

Like, share and follow me 😍 for more content on Dart.

Jermaine Oppong

Hello 👋, I show programmers how to build full-stack web applications with the Dart SDK. I am passionate about teaching others, having received tremendous support on sites like dev.to and medium.com for my articles covering various aspects of the Dart language and ecosystem.

Useful learning materials