2

I have this pretty simple Vue js page as below:

<html>
    <head>
        <script src="https://unpkg.com/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id="main-container">
            <div id="contact-table">
                <table>
                    <thead>
                        <tr>
                            <th>Contact Name</th>
                            <th>Email</th>
                        </tr>
                    </thead>
                    <tbody v-for="contact in contacts">
                        <tr v-on:click="selectContact(contact.index)">
                            <td>
                                {{contact.name}}
                            </td>
                            <td>
                                {{contact.email}}
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div id="contact-form">
                <input type="text" v-model="contactName"/>
                <input type="text" v-model="contactEmail"/>
                <button type="button" v-on:click="updateContact">Update Contact</button>
            </div>
        </div>
    </body>
    <script>
        var hub = {
            contacts: [
                {
                    name: "James",
                    email: "[email protected]",
                    index: 0
                },
                {
                    name: "Mary",
                    email: "[email protected]",
                    index: 1
                }
            ],
            index: 0
        };

        var contactTable = new Vue({
            el: "#contact-table",
            data: {
                contacts: hub.contacts
            },
            methods: {
                selectContact: function(index) {
                    hub.index = index;
                    console.log(hub.index);
                }
            }
        });

        var contactForm = new Vue({
            el: "#contact-form",
            data: {
                contactName: hub.contacts[hub.index].name,
                contactEmail: hub.contacts[hub.index].email
            },
            methods: {
                updateContact: function() {
                    hub.contacts[hub.index].name = this.contactName;
                    hub.contacts[hub.index].email = this.contactEmail;
                }
            }
        });
    </script>
</html>

Basically it contains two Vue parts - the table and the input form. By clicking the row in the table it should change the value in the input form and but clicking the Update contact button it should update the form details.

The second part is working well - however, when I clicked the table's row, although console.log tells me the hub.index is well updated, but the view in the input form is not.

I believe this should be a two-way binding here so I am just wondering where did I do wrong here.

1

1 Answer 1

1

Your hub variable is outside vue instance, so this varible is not reactive, meaning that if this variable change vue will not update the DOM. You can also define hub in the data part of vue and make it reactive.

You also need to have an event bus, as you want to communicate between your two components, You can send an event using $emit and listen to the component in other component using $on.

Here is the working fiddle for your code: https://jsfiddle.net/mimani/50ajs58L/1/

<script src="https://unpkg.com/vue/dist/vue.js"></script>

<body>
  <div id="main-container">
    <div id="contact-table">
      <table>
        <thead>
          <tr>
            <th>Contact Name</th>
            <th>Email</th>
          </tr>
        </thead>
        <tbody v-for="(contact, index) in contacts">
          <tr v-on:click="selectContact(index)">
            <td>
              {{contact.name}}
            </td>
            <td>
              {{contact.email}}
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <div id="contact-form">
      <input type="text" v-model="contactName" />
      <input type="text" v-model="contactEmail" />
      <button type="button" v-on:click="updateContact">Update Contact</button>
    </div>
  </div>
</body>
<script>
  var hub = {
    contacts: [{
      name: "James",
      email: "[email protected]",
      index: 0
    }, {
      name: "Mary",
      email: "[email protected]",
      index: 1
    }],
    index: 0
  };
  var bus = new Vue()
  var contactTable = new Vue({
    el: "#contact-table",
    data: {
      contacts: hub.contacts
    },
    methods: {
      selectContact: function(index) {
        hub.index = index;
        console.log(hub.index);
        bus.$emit('updateIndex', index)
      }
    }
  });

  var contactForm = new Vue({
    el: "#contact-form",
    data: {
      contactName: hub.contacts[hub.index].name,
      contactEmail: hub.contacts[hub.index].email,
      index: hub.index
    },
    methods: {
      updateContact: function() {
        hub.contacts[this.index].name = this.contactName;
        hub.contacts[this.index].email = this.contactEmail;
      }
    },
    created() {
      var that = this
      bus.$on('updateIndex', function(index) {
        that.index = index
        that.contactName = hub.contacts[that.index].name
        that.contactEmail = hub.contacts[that.index].email
      })
    }
  });

</script>

Here I have used event bus, but as your application grows, you can think of using a state management technique which will give you variables accessible to all the components, or you can use vuex which is popular among community. You can have a look at this and this answer for more details.

Sign up to request clarification or add additional context in comments.

2 Comments

If the app is complicated, vuex is absolutely recommended. For simple cases manually maintain data store is enough, like your answer do. However, creating multiple Vue instances in such a simple example looks like weird. I suggest OP to read through official docs and examples before take action :)
@Leo Thanks for that information. I haven't started taken action yet and this page is just for learning purpose. Vue js is pretty cool and I am trying to thinking in the way Vue js does.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.