0
votes

I am trying to build a basic form creator while trying to learn Vue. I am running into an issue where my v-model is not updating the data. The idea is you can add a type of field and it will add it to the form preview area on the top. There will also be a section where you can edit the data of that input. Currently I just have the label for each input and it will load the correct data into the input box but if I change it nothing changes in the actual data object.

Thinking it is a reactivity issue but still trying to get my head around it.

JSbin of it. http://jsbin.com/qudanosusa/edit?html,js,output

html

<!DOCTYPE html>
<html>
<head>
    <title>Form Builder</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" media="screen" href="/css/app.css">

</head>
<body>
<div class="container">

    <div class="row" id="app">

        <div class="col-md-8">
            <form class="form-horizontal">
                <my-component :showname="element.showname" :type="element.type" :name="element.name" :count="vm.count" v-for="element in elements"></my-component>
                <pre>{{ $data | json }}</pre>
                </form>
        </div>

        <div class="col-md-4">
            <div id="add_buttons">
                <p>
                <button @click="add_text_input" class="btn btn-primary">New Text Input Field</button>
                </p>
                <p>
                <button @click="add_text_area_input" class="btn btn-primary">New Text Area Field</button>
                </p>
            </div>
            <div id="features" class="row">
                <my-features :showname="element.showname" :type="element.type" :name="element.name" :count="vm.count" v-for="element in elements"></my-features>
            </div>
        </div>


    </div>

</div>
<template id="my-form">
    <div v-if="type == 'text'" class="form-group">
        <label v-bind:for="name" class="col-md-3 control-label">{{ showname }}:</label>
        <div class="col-md-8">
            <input type="text" v-bind:name="name" class="form-control">
        </div>
        <div class="col-md-1">
            <button class="btn" v-on:click="edit('element')">Edit</button>
        </div>
    </div>

    <div v-if="type == 'textarea'" class="form-group">
        <label v-bind:for="name" class="col-md-3 control-label">{{ showname }}:</label>
        <div class="col-md-9">
            <textarea v-bind:name="name" class="form-control"></textarea>
        </div>
    </div>
</template>

<template id="my-features">
    <div v-if="type == 'text'" class="form-group">
        <label v-bind:for="name" class="col-md-3 control-label">Label:</label>
        <div class="col-md-9">
            <input type="text" v-model="showname">
        </div>
    </div>

    <div v-if="type == 'textarea'" class="form-group">
        <label v-bind:for="name" class="col-md-3 control-label">{{ showname }}:</label>
        <div class="col-md-9">
            <textarea v-bind:name="name" class="form-control"></textarea>
        </div>
    </div>
</template>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
        integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
        crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.12/vue.min.js"></script>
<script>

</script>
</body>
</html>

js

var vm = new Vue({
        el: "#app",

        data: {
            elements: [{
                "name": "first_name",
                "showname": "First Name",
                "type": "text",
                "required": "false",
                "fee": "0",
                order: "1"
            }],
            count: 1
        },

        components: {
            'my-component': {
                template: '#my-form',
                props: ['showname', 'type', 'name', 'order']
            },
            'my-features': {
                template: '#my-features',
                props: ['showname', 'type', 'name', 'order']
            }

        },

        methods: {
            add_text_input: function () {
                vm.count ++;
                var array = {
                    name: "last_name",
                    showname: "Last Name",
                    type: "text",
                    required: "false",
                    fee: "0",
                    order: vm.count
                };
                this.elements.push(array);
            },
            add_text_area_input: function () {
                vm.count ++;
                var array = {
                    name: "last_name",
                    showname: "Last Name",
                    type: "textarea",
                    required: "false",
                    fee: "0",
                    order: vm.count
                };
                this.elements.push(array);
            },
            edit: function(element) {
                console.log(element);
            }
        }
    });
1

1 Answers

1
votes

Hey I've got your problem.

Its just a very simple issue.

<my-component 
    :showname="element.showname" 
    :type="element.type" 
    :name="element.name" 
    :count="vm.count" v-for="element in elements">
</my-component>

So in your component add sync to enable two way binding.

<my-component 
    :showname.sync="element.showname" 
    :type="element.type" 
    :name="element.name" 
    :count="vm.count" v-for="element in elements">
</my-component>

Here you can see I've added showname.sync which enables two way binding.

By Default when parents property updates, it flows down to its children but not in reverse. you'll have to add sync or once binding type modifiers.

Here's the link https://vuejs.org/guide/components.html#Prop-Binding-Types

Here's the jsBin http://jsbin.com/mitojijaya/1/edit?html,js,output

Hope this helps.