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 our 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 our 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 “Reverse message” button will print the Vue instance to the console.

The Vue instance. And we see the message property 😉

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:

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:

Watch the full video for a walkthrough of the other examples.

Conclusion

I hope this was insightful and you learnt something new today.

Subscribe to my YouTube channel for the latest videos on Dart. Thanks!

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

Further reading