What is the most effective method for transferring and accessing data within a child form component?

This is how I am currently handling it:

Parent.vue:

// Template

<form-child :schema="schema"><form-child>

// JS

data () {
  return {
    schema: [{ // name: '', value: '', type: '' }, { //etc ... }]
  }
}

FormChild.vue:

// Template

<div v-for="field in schema">
  <input v-if="field.type === 'text'" @change="updateValue(field.name, field.value)">
  <textarea v-if="field.type === 'textarea'" @change="updateValue(field.name, field.value)">/textarea>
</div>

// JS

props: {
  schema: Arrary
}

methods: {
  updateValue (fieldName, fieldValue) {
    this.schema.forEach(field => {
      // this will update the schema in Parent.vue
      if (field.name === fieldName) field.value = fieldValue
    })
  }
}

Do you think there might be a more effective way to handle this, maybe using emit and v-model? If so, could you please show me an example of how to implement that?

Answer №1

When creating a child component, it is important to ensure that it is decoupled from the parent data structure. The child component should have separate props for `type` and `value`, along with an opaque `id` to communicate which value is being emitted.

To enable the use of `v-model` on form elements within the component, a settable computed property based on the `value` parameter can be utilized. The `set` function triggers an `input` event containing the `id` and the new value, allowing the parent to handle the update.

Update: Upon further consideration, I decided to manage the `id` in the input handler:

@input="updateField(index, $event)
.

new Vue({
  el: '#app',
  data: {
    schema: [{
        type: 'text',
        name: 'one',
        value: "1"
      },
      {
        type: 'textarea',
        name: 'two',
        value: "stuff in the textarea"
      }
    ]
  },
  methods: {
    updateField(index, newValue) {
      this.schema[index].value = newValue;
    }
  },
  components: {
    formInput: {
      props: ['type', 'value'],
      computed: {
        proxyValue: {
          get() { return this.value; },
          set(newValue) {
            this.$emit('input', newValue);
          }
        }
      }
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="app">
  <div v-for="field in schema">
    {{field.name}} = {{field.value}}
  </div>
  <form-input inline-template v-for="field, index in schema" :type="field.type" :key="index" :value="field.value" @input="updateField(index, $event)">
    <div>
      <input v-if="type === 'text'" v-model="proxyValue">
      <textarea v-if="type === 'textarea'" v-model="proxyValue"></textarea>
    </div>
  </form-input>
</div>

Answer №2

Instead of breaking the form into a separate component, you can simply integrate it into the parent element and utilize v-model.

new Vue({
  el: '#app',
  data: {
    schema: [{
        type: 'text',
        name: 'one',
        value: "1"
      },
      {
        type: 'textarea',
        name: 'two',
        value: "stuff in the textarea"
      }
    ]
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="app">
  <div v-for="field in schema">
    {{field.name}} = {{field.value}}
  </div>
  <div v-for="field in schema">
    <input v-if="field.type === 'text'" v-model="field.value">
    <textarea v-if="field.type === 'textarea'" v-model="field.value"></textarea>
  </div>
</div>

If you prefer to create a component for reusability and are not concerned about isolating the parent from changes (although best practice is to avoid external changes to component data), you can enclose the same code within a component:

new Vue({
  el: '#app',
  data: {
    schema: [{
        type: 'text',
        name: 'one',
        value: "1"
      },
      {
        type: 'textarea',
        name: 'two',
        value: "stuff in the textarea"
      }
    ]
  },
  components: {
    formChild: {
      props: ['value']
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="app">
  <div v-for="field in schema">
    {{field.name}} = {{field.value}}
  </div>
  <form-child inline-template v-model="schema">
    <div>
      <div v-for="field in value">
        <input v-if="field.type === 'text'" v-model="field.value">
        <textarea v-if="field.type === 'textarea'" v-model="field.value"></textarea>
      </div>
    </div>
  </form-child>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The issue of linking .then() functions

I've been struggling to grasp the concept of Promises/then-ables for a while now. Currently, I am working with NextJS. My goal is to chain together the following steps: Retrieve data from an API Save the data Modify the data to create a component (w ...

What is the process for exporting/importing a variable in Node.js?

What is the correct way to export/import a variable in Node.js? I attempted to use export and import methods, but I received an error message stating that it should be a module. After changing the type to module in the JSON file, it then told me that requ ...

Autocomplete component fails to trigger onChange event upon losing focus in Mui framework

When using a Mui Autocomplete with the properties of multiple and freeSolo, a situation arises where pressing Return triggers an onChange event. However, when tabbing out of the Autocomplete widget, the typed text remains without updating the state of the ...

What is the significance of incorporating 'Actions' as data within the Redux framework?

According to Redux documentation, creating actions and action creators is necessary. Here's an example: function addTodo(filter) { return { type: SET_VISIBILITY_FILTER, filter } } Next step is to write reducers, like this: function t ...

What is the proper way to disable asynchronous behavior in JavaScript?

Can someone provide assistance on how to make the following jQuery ajax function asynchronous in this code? $.post(base_url+"search/questionBox/"+finalTopic+"/"+finalCountry+'/'+findSearchText+'/'+ID,function(data){ if (data != "") { ...

Check for equality with an array of objects when reacting to changes

I have an input field and an array of objects. I want the object with a property named "airplaneCompany" to be displayed as I type. Each character should be checked, and if the object's "airplaneCompany" property starts with 'a', it should b ...

The JavaScript code runs first before retrieving any information from the server

When it comes to validating coupons on Stripe, the process needs to be done on the server side rather than the client side. I've tackled this by writing some code for validation, but I'm facing challenges with synchronizing the AJAX/JSON response ...

All Event Monitor

Is it possible to use Event Listeners in jQuery to display information when a specific word is clicked? For example, showing a definition when a word is clicked. Thanks, Adam. I need help with creating a feature where clicking on a person's name in a ...

Vue and TypeScript: The elusive 'exports' remains unidentified

Since switching my App.vue to utilize typescript, I am facing a compiler error: [tsl] ERROR in \src\main.ts(2,23) TS2304: Unable to locate the name 'exports'. If I have vue-serve recompile after making changes, I encounter t ...

Add owl carousel to your npm project in any way you see fit

After struggling for a while, I finally wanted to implement owl-carousel, but couldn't figure out how to connect it using npm and webpack. The official NPM website states: Add jQuery via the "webpack.ProvidePlugin" to your webpack configuration: ...

Having trouble with adding an event listener on scroll in React JS. Need assistance in resolving this issue

I'm having trouble adding an event listener for when a user scrolls in my web app. componentDidMount = () => { let scrollPosition = window.scrollY; let header = document.getElementById("topBar"); window.addEventListener(&ap ...

Utilizing functions for object creation in JavaScript

Having trouble with creating a function that automatically generates an object and then alerts its properties. Can't seem to get the alerts when I click the button. Any assistance would be appreciated. <html> <head> <s ...

I am encountering a JQuery syntax error while using Bootstrap 3 button-dropdown links

I'm trying to replicate the example found here in order to create a similar markup: <div class="btn-group"> <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> ...

Guide to changing the background colors of multiple elements when hovered over by the mouse?

I want to customize my website's search bar by changing the background color when it is hovered over. Currently, the search bar has two main elements: the text box and the submit button. I have successfully programmed the text box element to change to ...

How can you trigger a link click event when clicking anywhere on the page using Jquery?

Here's the code I'm working with: <a href="http://google.com" target="_blank">Open in new tab </a> I am trying to make it so that when a user clicks anywhere on the website, the link above will be automatically clicked and a new tab ...

What strategies would you use to put in place conditional imports in a way that is reminiscent of ReactNative

Is there a way to implement conditional imports in other projects similar to how React Native imports Android or iOS specific classes using *.android.js and *.ios.js? If I wanted to have different classes for development and production purposes, could I u ...

Reorganize child JSON objects into a new object that includes a parent ID

Exploring the realm of JavaScript, I am currently delving into Node.JS to interact with an API and save the data in a SQL Server. Utilizing the "request" and "mssql" Node packages for this task as they possess robust documentation and support. My query re ...

Retrieve data from TypeScript file (.ts) and use it in an HTML document

Recently I started learning Typescript and HTML as I work on building an Angular2 application. At the moment, I have a TypeScript file that resembles the following structure: import {Http, Headers} from 'angular2/http'; import {Component} from & ...

The keyboard automatically disappeared upon clicking the select2 input

Whenever I select the select2 input, the keyboard automatically closes $('select').on('select2:open', function(e) { $('.select2-search input').prop('focus',false); }); Feel free to watch this video for more i ...

Capture a screenshot of the icons

I'm curious about displaying specific parts of images in a React Native application. class InstaClone extends Component { render() { return( <View style={{ flex:1, width:100 + "%", height:100 + "%" }}> <View style={st ...