0

I am trying to refresh component data from another component. When a user clicks 'Save Changes' I send post, insert data into db in laravel from CreateNewAccessGroupModal template. Then, after response success I need to refresh component (AccessGroup template) and show updated row in view (access_groups arr). What I need to do to achieve it? I can not understand how to use defineEmits properly.

Main template:

<template>
  <MainLayout title="Access Groups" :sidebar="true">
    <main class="main main-p">
      <div class="main-content">
        <div class="main-head">
          <ul class="breadcrumbs">
            <li class="breadcrumbs-item">
              <a href="#" class="breadcrumbs-link">
                <i class="ico-home"></i>
              </a>
            </li>
            <li class="breadcrumbs-item">
              <a href="#" class="breadcrumbs-link">Settings</a>
            </li>
            <li class="breadcrumbs-item">
              <a href="#" class="breadcrumbs-link">Assets groups</a>
            </li>
          </ul>

          <h1 class="main-head__title">Access Groups</h1>
        </div>

        <div class="main-actions">
          <div class="main-actions__wrap">
            <div class="main-actions__btns">
              <a
                href="#modalCreateAccessNewGroup"
                class="btn btn-bordered"
                data-toggle="modal"
              >
                <i class="ico-plus"></i>
                Create group
              </a>
              <button class="btn btn-light">
                Delete
                <i class="ico-delete"></i>
              </button>
            </div>
          </div>
        </div>

        <div class="main-body">
          <div class="table">
            <div class="table-head">
              <div class="table-head__wrap">
                <div class="table-head__item table-head__item-checkbox">
                  <div class="checkbox">
                    <input
                      type="checkbox"
                      class="checkbox-input"
                      id="checkboxGroupNameAll"
                    />

                    <label
                      for="checkboxGroupNameAll"
                      class="checkbox-label"
                    ></label>
                  </div>
                </div>

                <div class="table-head__item">Group name</div>

                <div class="table-head__item table-head__item-btn"></div>

                <div class="table-head__item table-head__item-btn"></div>
              </div>
            </div>

            <div class="table-body">
              <div class="table-body__wrap">
                <AccessGroup :access_groups="access_groups" />
              </div>
            </div>
          </div>
        </div>
      </div>
    </main>
  </MainLayout>

  <CreateNewAccessGroupModal :permissions_param="permissions_param" />
</template>

CreateNewAccessGroupModal template:

<template>
  <div
    class="modal fade"
    id="modalCreateAccessNewGroup"
    tabindex="-1"
    role="dialog"
    aria-labelledby="modalCreateNewGroup"
    aria-hidden="true"
    data-backdrop="static"
  >
    <div class="modal-dialog modal-dialog-centered" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h3 class="modal-title">Create new group</h3>

          <button
            type="button"
            class="close"
            data-dismiss="modal"
            aria-label="Close"
          >
            <i class="ico-close"></i>
          </button>
        </div>

        <form @submit.prevent="createNewAccessGroup">
          <div class="modal-body">
            <div class="modal-box">
              <div class="modal-hold">
                <div class="input">
                  <label class="input-label">Group name:</label>

                  <div class="input-box">
                    <input
                      v-model="group_name"
                      type="text"
                      class="input-field"
                    />

                    <span class="invalid-feedback">Required field</span>
                  </div>
                </div>

                <div class="input">
                  <label class="input-label">Description:</label>

                  <div class="input-box">
                    <input
                      v-model="description"
                      type="text"
                      class="input-field"
                    />

                    <span class="invalid-feedback">Required field</span>
                  </div>
                </div>
              </div>

              <div class="attribute">
                <div class="attribute-head">Permissions</div>

                <div
                  v-for="(permission, index) in permissions_param"
                  :key="index"
                  class="attribute-body"
                >
                  <div class="attribute-row">
                    <div class="checkbox">
                      <input
                        v-model="permissions"
                        :value="index"
                        type="checkbox"
                        class="checkbox-input"
                        :id="index"
                      />

                      <label :for="index" class="checkbox-label"></label>
                    </div>

                    {{ permission.label }}
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div class="modal-footer modal-footer__end">
            <div class="modal-text">
              By clicking save button API key for the group will be generated
            </div>

            <button id="close" class="btn btn-m-secondary" data-dismiss="modal">
              Cancel
            </button>

            <button class="btn btn-m-primary">Save Changes</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</template>

<script setup>
  import { ref } from "vue";
  import { useForm } from "@inertiajs/inertia-vue3";

  let props = defineProps({
    permissions_param: Array,
  });

  const emit = defineEmits(["update-permissions"]);

  let group_name = ref("");
  let description = ref("");
  let permissions = ref([]);

  function createNewAccessGroup() {
    axios
      .post("/access-group/create-new", {
        group_name: group_name.value,
        description: description.value,
        permissions: permissions.value,
      })
      .then(function (response) {
        if (response.data.success) {
          emit("update-permissions", response.data.success);
        } else {
          //show warning
        }
      })
      .catch(function (error) {});
  }
</script>

AccessGroup template:

<template>
  <div
    v-for="(access_group, index) in access_groups"
    :key="index"
    class="table-row"
  >
    <div class="table-row__item table-row__item-checkbox">
      <div class="checkbox">
        <input type="checkbox" class="checkbox-input" id="checkboxGroupName1" />
        <label for="checkboxGroupName1" class="checkbox-label"></label>
      </div>
    </div>

    <div class="table-row__item">
      <span class="table-row__item-box">{{access_group.group_name}}</span>
    </div>

    <div class="table-row__item table-row__item-btn">
      <a href="#modalViewUsers" class="btn btn-m-secondary" data-toggle="modal"
        >Users</a
      >
    </div>

    <div class="table-row__item table-row__item-btn">
      <a
        href="#modalEditAccessGroup"
        class="btn btn-m-secondary"
        data-toggle="modal"
      >
        Details
        <i class="ico-edit"></i>
      </a>
    </div>
  </div>

  <EditAccessGroupModal />

  <ViewAccessGroupUsersModal />
</template>
ericmp
  • 1,163
  • 4
  • 18
Jack88
  • 1
  • 3
  • [Here](https://stackoverflow.com/a/74317057/14569750) you have an example on how to share data from a child component to its parent – ericmp Jan 05 '23 at 11:24
  • ericmp,thanks for answer. Could you show small example with my data please. I do not understand exactly example. – Jack88 Jan 05 '23 at 12:05
  • emit won't work, because these components are siblings, not parent-child – Anton Platon Jan 05 '23 at 15:38

1 Answers1

0

Vue is reactive by default.
In case you use state manager (Vuex/Pinia) - inside the CreateNewAccessGroupModal just put response's result to your store. In the AccessGroup you can get a reference to that value in the store. Once you update store with new value inside the CreateNewAccessGroupModal, the AccessGroup should receive new value. Why? Because Vue.js is reactive by default. Some API of Vuex that should help you - https://vuex.vuejs.org/guide/actions.html , https://vuex.vuejs.org/guide/state.html , https://vuex.vuejs.org/guide/composition-api.html . Pinia has similar solutions.

In case you do not use state manager - it depends on the organisation of your components and business requirements). If I were you, I would used provide/inject of Vue3 - https://vuejs.org/guide/components/provide-inject.html .
Your Main template is a parent for both components, so only Main template is able to "speak" with both components. Inside Main I would define 1) ref object to put result of response in and 2) the method to do it, for example

// Main.vue
<script>
import { ref, provide } from 'vue'
const resultOfResponse = ref(null)
const putResultInside = (result) => {
  resultOfResponse.value = result;
}
// PROVIDE IT FOR YOUR descendants (AccessGroup, CreateNewAccessGroupModal etc) !
provide('MainProvide', {
  resultOfResponse,
  putResultInside,
})

and I would use it inside components:

// CreateNewAccessGroupModal.vue
<script>
import { inject } from 'vue'
//...
const {putResultInside} = inject('MainProvide')
const makeRequest = () => {
//...
  putResultInside(reponse.data.your.result)
}

// AccessGroup.vue
<script>
import { inject } from 'vue'
// use it as you wish :)
const {resultOfResponse} = inject('MainProvide')

Sometimes provide/inject are not explicit enough, in this case you can use provide/inject only for CreateNewAccessGroupModal.vue, but pass resultOfResponse from Main to AccessGroup via props. As you wish)
Why won't emit work? Emit will work only if you have "conversation" between parent-child components.
As I can see, your components are siblings, they cannot "catch" emits of each other.