Using NativeScript DataForm with Vue.js - Some Tips

Using NativeScript DataForm with Vue.js - Some Tips

This post is more than 2 years old.

As I've mentioned recently, I'm currently working on a NativeScript Vue application for a client and as part of that work, I'm dealing with custom forms. My initial approach made use of custom components, which Vue made pretty trivial, but I've decided to give NativeScript UI a try. This is a set of free components covering the following features:

  • Calendar
  • Chart
  • ListView
  • DataForm
  • SideDrawer
  • Gauge
  • AutoComplete

Specifically, DataForm looked like it could be useful. While it's not too difficult to build forms with NativeScript, DataForm attempts to automate as much as possible of the process. As an example, consider the following data:

{
	"name":"Raymond Camden",
	"yearBorn":1973,
	"cool":true,
	"email":"raymondcamden@gmail.com"
}

Now imagine we tie this to a dataform control:

<RadDataForm ref="dataForm" :source="person" />

And if we literally leave it at this - the control will automatically render a nice form for us:

Screenshot of form

Notice how the control looked at my data properties and figured out what controls to use as well as how to create labels. yearBorn for example becomes Year Born. This all happens by default and is freaking cool, but you can control all of this as well if you don't care for their defaults.

All in all a neat little control, but I ran into some issues right away as soon as I started trying some of the more advanced features. Part of this is due to some poor docs (I've already sent reports in!) and I hope this post can help others avoid the issues I ran into.

Install with Vue Issues

So the docs tell you to install the relevant plugin, but right after that things go a bit awry.

The "Getting Started" for the Vue docs and DataForm, which isn't even labelled that (in the nav it's called "Provide the Source" tell you to do this:

"Add this to the main Javascript or Typescript file, usually called main.js or main.ts:"

import RadDataForm from 'nativescript-ui-dataform/vue';

Vue.use(RadListView);
Vue.use(RadDataForm);

Ok, I did that. Then it says:

"Before proceeding, make sure that the nativescript-ui-dataform/vue module is required inside your application. This module handles the registration of the custom directives and elements required by nativescript-vue.

After that simply add the RadDataForm tag to the HTML and set its source accordingly: "

So that first paragraph didn't make sense. I mean, didn't I already do that? To make matters worse, the code sample below doesn't provide any additional help.

I was only able to get things working by going to the NativeScript Playground, dragging a DataForm control on the page, and looking at what it did.

Based on that, this is what worked for me:

  1. Do not add code to main.js/maint.js. From what I can see it wasn't necessary.

  2. In your component, do require the dataform like so:

Edit on 11/7/2018, a mere hour after posting... @bundyo reduced the original 5 lines of code I had to just one:

import 'nativescript-ui-dataform/vue';

Looking at that code, the paragraph I quoted above makes sense now, but I had no idea what code to even use. If the code sample on the page had included this, it would have saved me about two hours - I kid you not.

Working with Groups

Alright - so the main reason I even looked at the dataform control was to make use of the "groups" feature. This lets you take a large form and create groups that can ben opened and collapsed. It isn't an "accordion" control per se, but it achieves the same purpose. (For folks curious, there is a NativeScript Accordion control but it has certain restrictions that made it unusable for my case.) Here are two screenshots I stole from the docs - first the Android version:

Android example of Groups

And then iOS:

iOS Groups example

So, while cool, the docs on this were pretty slim, especially in regards to providing dynamic groups, by that I mean groups defined in data and not hard coded as tags on the page. I spent a heck of a lot of time trying to get this to work and finally gave up and asked for help on the NS Slack group. Thankfully @bundyo came to the rescue. What follows is his solution, not mine. My data is still hard coded but you can see where it could be modified to support data loaded from Ajax or some such.

<template>
    <Page class="page">
        <ActionBar title="Demo" class="action-bar" />
        <ScrollView>
            <RadDataForm  ref="dataForm" :source="album" :metadata="md" :groups="groups">
            </RadDataForm>
        </ScrollView>
    </Page>
</template>

<script>
import { RadDataForm, PropertyGroup } from 'nativescript-ui-dataform';

require("nativescript-vue").registerElement(
    "RadDataForm",
    () => require("nativescript-ui-dataform").RadDataForm
);

export default {
    data() {
        return {
            groups:[],
            album: {
                bandName: "Edwhat Sheeran",
                albumName: "X",
                year: "2017",
                owned: true,
                myRating: 9.5,
            },
            md:{

            }
        };
    },
    created() {

        this.md = {                 
            propertyAnnotations:[
                    {
                        name:"bandName",
                        displayName:"My band name",
                        required:true,
                        groupName:"Group One"
                    },
                    {
                        name:"albumName",
                        displayName:"My album",
                        required:true
                    },
                    {
                        name:"year",
                        required:true,
                        groupName:"Group One"
                    },
                    {
                        name:"owned",
                        required:true,
                        groupName:"Group Two"
                    },
                    {
                        name:"myRating",
                        required:true,
                        groupName:"Group Two"
                    }
                ]
        };

        let pg = new PropertyGroup(); 
        
        pg.name = "Group One"; 
        pg.collapsible = true;
        pg.collapsed = false;
            
        this.groups.push(pg);

        pg = new PropertyGroup(); 
        
        pg.name = "Group Two"; 
        pg.collapsible = true;
        pg.collapsed = true;
            
        this.groups.push(pg);

    }
};
</script>

<style scoped>
</style>

Let's break it down. First, look at the dataform:

<RadDataForm  ref="dataForm" :source="album" :metadata="md" :groups="groups">
</RadDataForm>

There's two new attributes here - metadata and groups. So metadata is where you can do overrides on the default behaviors of the control. Don't like the label it selects for your property value? You can tweak it here. Want to use a custom drop down with specific values? You can set it here. We use this feature to specify the groups for each field. (And again, it's hard coded here but it could be dynamic.)

The next part is creating the groups. In this case we use an instance of PropertyGroup, one for each group, and ensure that the names match the names used in metadata.

If you want to see, and play with, a slimmer version, check out the Playground @bundyo made here: https://play.nativescript.org/?template=play-vue&id=qWbsL5&v=3 It really does a nice job of setting up the groups and fields all in one fell swoop. And because it's on the Playground, you can point the NativeScript Playground app at it and have it running on your device in 10 seconds.

Groups example running on phone

Anyway, I hope this helps. As I said, the docs here were a bit painful, but I've sent multiple reports in to the NativeScript folks so hopefully it gets improved soon. If you have any questions, just drop me a line below!

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by zzzxtreme posted on 12/11/2018 at 7:24 AM

the lack of complete vue examples is worrying. too bad, because vue + vuex is awesome

Comment 2 (In reply to #1) by Raymond Camden posted on 12/11/2018 at 2:54 PM

IMO, the Vue stuff is growing. It's certainly not just me blogging about it. :)

Comment 3 by hgc2002 posted on 4/20/2019 at 10:01 AM

Impossible to make it run. My error message is: "Cannot read property 'ExpandableEditorGroup' of undefined". It's an issue coming from the plugin. It's buggy. The proof is that you had to make some unnecessary magic when doing this part:


require("nativescript-vue").registerElement( "RadDataForm",
() => require("nativescript-ui-dataform").RadDataForm
);

For a very well known plugin, getting into this issues is unbelievable.

Note: Sorry but I was playing with the feedback icons and I click on "Sad" but the article is good. I don't know how to change it to "Upvote".

Comment 4 (In reply to #3) by hgc2002 posted on 4/20/2019 at 10:58 AM

I found a workaround. See: https://github.com/NativeSc...

But even after the tns update (that should fix everything), the "magic" of registerElement is still required...

Comment 5 by Andrew posted on 4/30/2019 at 9:46 PM

But how do we get the input values in Vue? How do we submit the form? Have you found any way to change the styles of a Picker input?

Comment 6 (In reply to #5) by Raymond Camden posted on 5/1/2019 at 7:32 PM

1) Since you tie the form to your data, your input values is your data. Does that make sense?

2) Submitting is something you would do yourself via an HTTP call.

3) And sorry - haven't done anything with styles.

Comment 7 by Prashant posted on 7/15/2019 at 10:53 AM

but how do you submit the form which event or method need to fire or caputre the data

Comment 8 (In reply to #7) by Raymond Camden posted on 7/15/2019 at 1:38 PM

Submitting the form would be done via click handler on a button. The data doesn't need to be captured, it's already there. Remember we find the form to your Vue data. So you have it already.

Comment 9 (In reply to #8) by Prashant posted on 7/16/2019 at 7:54 AM

Thanks You are right

Comment 10 by Prashant posted on 7/16/2019 at 7:56 AM

One more query I was checking example 1 where in dropdown list was created but a converter function which i don't understand how it works can you add. https://docs.nativescript.o... Example 1. How do we handle the drop down list box values changed.

Request you to please add drop down list box example here with plain javascript

Comment 11 (In reply to #10) by Raymond Camden posted on 7/16/2019 at 12:52 PM

I'm not quite sure I get what you are asking. Are you asking for an example of how to handle drop downs, and by handle I mean provide the values? If so the docs you linked to do show that. Maybe you can rephrase?

Comment 12 (In reply to #11) by Prashant posted on 7/18/2019 at 3:18 PM

can you fork this example https://play.nativescript.o... Kindly check Test.vue field movie is drop down list box kindly check line no 92 I want to add array having id, text filed array. Once I submit the form should get movie=1121.

Sorry came from Desktop application development we called it Lisbox as Drop Down List Box (DDLB).

Thanks in advance.

Comment 13 by Prashant posted on 7/23/2019 at 7:32 AM

its not working here is the code can you forked and check https://play.nativescript.o...

Comment 14 (In reply to #13) by Raymond Camden posted on 7/23/2019 at 12:56 PM

I've been on the road. I see your request below and will look into it when I can.

Comment 15 (In reply to #14) by Prashant posted on 7/27/2019 at 5:00 AM

Don't woory I resoled this issue I will create a playground and post it soon. Thanks for your help

Comment 16 by Prashant posted on 8/27/2019 at 2:01 PM

Its working just add dataEntry component and remove it will update NPM pacakges and it works.

Comment 17 by Prashant posted on 8/27/2019 at 2:02 PM

can you add date picker with date format that is completely missing in documentation.

Comment 18 (In reply to #17) by Raymond Camden posted on 8/27/2019 at 2:52 PM

Add it to the docs? I don't work for Progress. :)

Comment 19 (In reply to #18) by Prashant posted on 8/28/2019 at 3:41 AM

yes thaks I reported lot of missing documentation for vue but unfortunately I didn add my email address so i didn't get any notification. Now I saw it was reflecting. Now I will remember it. Thanks but your blog powered us to make it possible.

Comment 20 by Prashant posted on 8/28/2019 at 3:44 AM

Just need a suggetion from you Since vue next version comes up with Typescipt. What you will suggest to moved it to Typescript or continue with Javascript?

Comment 21 (In reply to #20) by Raymond Camden posted on 8/30/2019 at 8:44 PM

I say work with what makes you most productive. I like TS, but don't use it very often.

Comment 22 by Ralf Bordé posted on 12/11/2019 at 12:30 PM

Hi Raymand, thx for your great article. If i try this, my iOS-Form looks very weird. Is there a fitting css for this form? This is what it looks like: https://uploads.disquscdn.c...
Thanks in advance. Greetings from germany. Ralf

Comment 23 by Lucas posted on 1/7/2020 at 4:18 PM

Thanks for that, it helps a lot on understanding the radDataForm, but it still lacks so much information on how it works that seems faster to create my own vue form components than using it :/
I'm 1 day long trying to figure out how i change datepicker output format.. so annoying..

Comment 24 (In reply to #23) by Raymond Camden posted on 1/8/2020 at 2:03 PM

Sorry - I haven't used NS in a while now.

Comment 25 by Oscar LD posted on 2/15/2020 at 3:52 PM

¿Do you know how to add an image label to my field? using the metadata JSON it doesn't work

...
name:'email',
displayName: '',
hintText:' Email',
editor: 'Email',
imageResource:"res://ic_email"
...

Comment 26 (In reply to #25) by Raymond Camden posted on 2/17/2020 at 3:05 PM

Sorry I haven't used this since 2018.