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.
Watch the video
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 http://localhost:8080
.
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:
See the full video for a detailed walkthrough. Thanks for reading!