Vue/Nuxt is there a proper pattern for loading and editing component data without lifecycle hooks

Use Case: I have a component that contains a datatable, that lists Applications, I click a row and it opens a component with the fields loaded appropriately (new or edit).

The Problem: a component loads a ** reference ** of the data, new or existing, that I can bind to in a component. Because it is not a copy, I cannot edit it.

Quick explanation on the code: New() calls Open(), both load the Component ViewApplication.

Datatable Component

<template>
  <div id="inspire" data-app>
      <v-card>
        <v-banner single-line>
              <v-btn @click="New">New</v-btn>
        </v-banner>
        <v-card>
          <v-layout>
            <v-list-item>
              <v-list-item-content>
                <v-row>
                  <v-col>
                    <v-data-table
                      :items="items"
                      return-object
                      @click:row="Open"
                    >
                      <template #top>
                        <v-dialog v-model="dialog" max-width="600">
                          <ViewApplication
                            :loadedapp="loaded"
                            @reload="Load"
                            @close="close"
                          />

                        </v-dialog>
                      </template>
                    </v-data-table>
                  </v-col>
                </v-row>
              </v-list-item-content>
            </v-list-item>
          </v-layout>
        </v-card>
      </v-card>
  </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex'
export default {
  data: () => ({
    dialog: false,
    items: this.LoadApplications(),
  }),
  computed: {
    ...mapGetters({
      applications: 'modules/Manage/getApplications',
    }),
  },
  methods: {
    ...mapActions({ LoadApplications: 'modules/Manage/LoadApplication' }),
    Open(item) {
      console.log('Open item: ' + item)
      this.loaded = item
      this.$store.commit('modules/Manage/setApplication', item)
      this.dialog = true
    },
    New() {
      let item = { app_name: '', roles: `[]`, api: '' }
      this.Open(item)
    },

  },
}
</script>

ViewApplication Component

<template>
  <v-card v-if="loadedapp">
    <v-col>
      <v-text-field v-model="app_name" dense label="Application Name" />
      <v-row>
        <v-col col="6">
          <v-text-field
            v-model="role"
            label="Role"
            :append-outer-icon="'mdi-send'"
            @click:append-outer="roles.push(role)"
          />
        </v-col>
        <v-col col="6">
          <v-select
            v-model="roles"
            :items="roles"
            :menu-props="{ maxHeight: '400' }"
            label="Roles"
            multiple
          ></v-select>
        </v-col>
      </v-row>

      <v-text-field v-model="api" dense label="API" />
    </v-col>
    <v-card-actions>Save, Delete</v-card-actions>
  </v-card>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  props: {
    loadedapp: {
      type: Object,
      default: () => {
        return { app_name: '', roles: `[]`, api: '' }
      },
    },
  },
  data() {
    return {
      localapp1: this.getApp,
      localapp2: { ...this.getApp },
      localapp3: this.loadedapp,
      localapp4: { ...this.loadedapp },
      role: '',
      app_name: '',
      roles: [],
      api: '',
    }
  },
  computed: {
    ...mapGetters({
      path: 'modules/Auth/gutCustomerURL',
      getApp: 'modules/Manage/getApp',
    }),
  },
}
</script>

DevTools

Answer

Found these links instructive: https://vuex.vuejs.org/guide/forms.html https://markus.oberlehner.net/blog/form-fields-two-way-data-binding-and-vuex/

Actual solution:

  props: {
    loadedapp: {
      type: Object,
      default: () => {
        return { app_name: '', roles: `[]`, api: '' }
      },
    },
  },
  data() {
    return {
      role: '',
      app_name: '',
      roles: [],
      api: '',
    }
  },
  watch: {
    loadedapp: {
      immediate: true,
      handler() {
        this.init()
      },
    },
  },
  methods: {
    init() {
      if (this.loadedapp) {
        this.app_name = this.loadedapp.app_name
        this.roles = JSON.parse(this.loadedapp.roles)
        this.api = this.loadedapp.api
      }
    },}