Creating and showing complex JSON object dynamically using VueJS component and HTML

Viewed 136

I am developing a Vuejs application within which I have a field extension. For this field, users can provide the values and this field expands dynamically (both vertically and horizontally) based on the user-provided values.

I am using the recursive component ExtensionComponent to display and store the values. But it's not working as expected for me.

The field name extensions displays, initially an Add Extension. With on click of the button, a bootstrap modal will be displayed which has 3 fields: namespace (text), localname (text), datatype(dropdown: string/complex). If the datatype is string then a simple text field will be displayed. However, if the datatype is complex then another button should be displayed and on click of the button again the same bootstrap modal is displayed with fields and the process continues. So the created JSON based on this will expand horizontally and vertically.

I am able to create the Vue component to show the recursive data but I am a bit confused about the addition of the values to extensionList array dynamically. Can someone please help me with this issue?

Following is my Test.vue page which will display the Extensions and Add Button:

<template>
  <div>
    <span>Extensions</span>
    <button class="btn btn-primary" @click="createExtensions">
      Add Another
    </button>

    <ExtensionComponent :extension-list="$store.state.extensionList" />
    <TestModal v-if="$store.state.showModal" />
  </div>
</template>

<script>
import TestModal from '@/components/TestModal.vue'

export default {
  computed: {
    TestModal
  },
  methods: {
    // Method to create extensions and add
    createExtensions () {
      this.$store.commit('toggleExtensionModal')
    }
  }
}
</script>

<style>

</style>

Following is my Bootstrap modal (TestModal.vue) which will be displayed whenever Add Another button is clicked (initially and for complex):

<template>
  <b-modal
    id="Extension"
    title="Add Another Element"
    size="lg"
    width="100%"
    :visible="$store.state.showModal"
  >
    <b-form id="AddExtension" @submit.prevent="submitExtension">
      <div class="form-group">
        <label for="message-text" class="col-form-label">Namespace URI:</label>
        <input
          v-model="extension.namespace"
          type="text"
          class="form-control"
          required
        >
      </div>
      <div class="form-group">
        <label for="message-text" class="col-form-label">Local Name:</label>
        <input
          v-model="extension.localName"
          type="text"
          class="form-control"
          required
        >
      </div>
      <div class="form-group">
        <label
          for="AddExtensionDataType"
          class="col-form-label"
        >Data Type:</label>
        <b-form-select v-model="extension.dataType" class="form-control">
          <b-form-select-option value="string">
            String
          </b-form-select-option>
          <b-form-select-option value="complex">
            Complex
          </b-form-select-option>
        </b-form-select>
      </div>
    </b-form>
    <template #modal-footer="{ cancel }">
      <b-btn @click="cancel">
        Cancel
      </b-btn>
      <b-btn variant="primary" type="submit" form="AddExtension">
        OK
      </b-btn>
    </template>
  </b-modal>
</template>

<script>
export default {
  data () {
    return {
      extension: {
        namespace: '',
        localName: '',
        dataType: 'string'
      },
      showModal: false
    }
  },
  methods: {
    submitExtension () {
      // Call vuex store to save information
      this.$store.commit('addExtension', this.extension)

      // Hide modal after submitting modal
      this.$store.commit('toggleExtensionModal')
    }
  }
}
</script>

<style>
</style>

Following is my ExtensionComponent.vue which will display data recursively:

<template>
  <div>
    <div
      v-for="extension in extensionList"
      :key="extension.ID"
      class="form-inline"
    >
      <span>{{ extension.namespace + ":" + extension.localName }}</span>
      <input
        v-if="extension.dataType == 'string'"
        type="text"
        @input="$emit('AddExtensionText', {$event, id: extension.ID})"
      >
      <ExtensionComponent v-if="extension.dataType == 'complex'" :extension-list="extension" @AddExtensionText="AddExtensionText($event)" />
      <button
        v-if="extension.dataType == 'complex'"
        @click="AddComplextExtension(extension.ID, extension)"
      >
        Add another
      </button>
    </div>
  </div>
</template>

<script>
import ExtensionComponent from '@/components/ExtensionComponent.vue'

export default {
  components: {
    ExtensionComponent
  },
  props: {
    extensionList: Array,
    extension: Object
  },
  methods: {
    AddComplextExtension (extensionID, extension) {
      this.$store.commit('modules/ExtensionDataStore/showExtensionModal')
    },
    AddExtensionText ({ value, id }) {
      const i = this.extensionList.findIndex(el => el.ID === id)
      this.$set(this.extensionList, i, value)
    }
  }
}
</script>

Following is my index.js Vuex store:

export const state = () => ({
  extensionID: 0,
  extensionList: [],
  showModal: false
})

export const mutations = {
  toggleExtensionModal (state) {
    // Function to show/hide the extension Modal
    state.showModal = !state.showModal
  },
  addExtension (state, extension) {
    console.log(extension)
    extension.ID = state.extensionID
    state.extensionList.push(extension)
    state.extensionID++
  }
}

export const actions = {}

Following is the front-end I have: enter image description here

I want to create JSON and show it something like this: enter image description here

As we can see if the value is complex then the field is created dynamically and displayed in a parent-child relationship way. I am a bit confused about how to establish the parent-child relationship within complex JSON and show them to the user. Someone,Ad

0 Answers
Related