Home > database >  Getting values from modal to main view in VUE
Getting values from modal to main view in VUE

Time:02-18

I make my first project in Vue.

I have small problem. I need to get a value from Datatable (marked in code: console.log (self.selectedContent); // here is my result @@) - to my main view and display it. How can I do this?

My Main.vue:

<template>
  <CCard>
    <CCardHeader>
      <CIcon name="cil-input-power"/>
      Dodaj zlecenie
    </CCardHeader>
    <CCardBody>
      <CRow>
        <CCol sm="12">
          <CForm>
            <div  id="myTabContent">
              <div  : id="tab1">
                <h4 >Dane przewoźnika </h4>

                <CButton
                  @click="warningModal = true"
                  color="primary"
                >
                  Uzupełnij
                </CButton>
                <CInput
                  v-model.trim="$v.form.carrier_id.$model"
                  :isValid="checkIfValid('carrier_id')"
                  type="hidden"
                />
                <CRow>
                  <CCol md="6">
                    <CInput
                      maxlength="255"
                      label="Nazwa przewoźnika*"
                      v-model.trim="$v.form.carrier_name.$model"
                      :isValid="checkIfValid('carrier_name')"
                      placeholder="Wpisz nazwę przewoźnika"
                      invalidFeedback="To pole jest wymagane i musi zawierać minimum 3 znaki i maksimum 255 znaków"
                    />
                  </CCol>
                  <CCol md="6">
                    <CInput
                      maxlength="255"
                      label="NIP przewoźnika*"
                      v-model.trim="$v.form.carrier_nip.$model"
                      :isValid="checkIfValid('carrier_nip')"
                      placeholder="Wpisz NIP przewoźnika"
                      invalidFeedback="To pole jest wymagane i musi zawierać minimum 3 znaki i maksimum 255 znaków"
                    />
                  </CCol>
                </CRow>
                <CRow>
                  <CCol md="6">
                    <CInput
                      maxlength="255"
                      label="Regon przewoźnika*"
                      v-model.trim="$v.form.carrier_regon.$model"
                      :isValid="checkIfValid('carrier_regon')"
                      placeholder="Wpisz regon przewoźnika"
                      invalidFeedback="To pole jest wymagane i musi zawierać minimum 3 znaki i maksimum 255 znaków"
                    />
                  </CCol>
                  <CCol md="6">
                    <CInput
                      maxlength="255"
                      label="Email przewoźnika*"
                      v-model.trim="$v.form.carrier_email.$model"
                      :isValid="checkIfValid('carrier_email')"
                      placeholder="Wpisz email przewoźnika"
                      invalidFeedback="To pole jest wymagane i musi zawierać minimum 3 znaki i maksimum 255 znaków"
                    />
                  </CCol>
                </CRow>
                <CRow>
                  <CCol md="6">
                    <CInput
                      maxlength="255"
                      label="Telefon przewoźnika*"
                      v-model.trim="$v.form.carrier_phone.$model"
                      :isValid="checkIfValid('carrier_phone')"
                      placeholder="Wpisz telefon przewoźnika"
                      invalidFeedback="To pole jest wymagane i musi zawierać minimum 3 znaki i maksimum 255 znaków"
                    />
                  </CCol>
                  <CCol md="6">
                    <CInput
                      maxlength="255"
                      label="Kod pocztowy przewodnika*"
                      v-model.trim="$v.form.carrier_postal_code.$model"
                      :isValid="checkIfValid('carrier_postal_code')"
                      placeholder="Wpisz kod pocztowy przewodnika"
                      invalidFeedback="To pole jest wymagane i musi zawierać minimum 3 znaki i maksimum 255 znaków"
                    />
                  </CCol>
                </CRow>
                <CRow>
                  <CCol md="6">
                    <CInput
                      maxlength="255"
                      label="Adres przewoźnika*"
                      v-model.trim="$v.form.carrier_street.$model"
                      :isValid="checkIfValid('carrier_street')"
                      placeholder="Wpisz adres przewoźnika"
                      invalidFeedback="To pole jest wymagane i musi zawierać minimum 3 znaki i maksimum 255 znaków"
                    />
                  </CCol>
                  <CCol md="6">
                    <CInput
                      maxlength="255"
                      label="Miasto przewodnika*"
                      v-model.trim="$v.form.carrier_city.$model"
                      :isValid="checkIfValid('carrier_city')"
                      placeholder="Wpisz miasto przewodnika"
                      invalidFeedback="To pole jest wymagane i musi zawierać minimum 3 znaki i maksimum 255 znaków"
                    />
                  </CCol>
                </CRow>
                <CRow>
                  <CCol md="12">
                    <CInput
                      maxlength="255"
                      label="Email do powiadomień*"
                      v-model.trim="$v.form.carrier_email_to_notification.$model"
                      :isValid="checkIfValid('carrier_email_to_notification')"
                      placeholder="Wpisz email do powiadomień"
                      invalidFeedback="To pole jest wymagane i musi zawierać minimum 3 znaki i maksimum 255 znaków"
                    />
                  </CCol>
                </CRow>
                <h4 >Kierowca </h4>
                <CRow>
                  <CCol md="12">
                    <CSelect id="driver_id"
                             label="Wybierz kierowcę"
                             v-model.trim="$v.form.driver_id.$model"
                             :options="drivers"
                    >
                    </CSelect>
                  </CCol>
                </CRow>
                

                <h4 >Rodzaj przewożonego towaru </h4>
              
                <template v-for="(option) in productDircionary">
                  <div  :key="option.name">
                    <CCol sm="12">
                      <input type="checkbox" name="selectedProducts[]" :value="option.value" v-model="selectedProducts"
                             :id="option.value" :checked="selectedProducts.includes(option.value)"/> {{ option.label }}
                    </CCol>
                  </div>
                </template>


                <div>wybrano: {{ selectedProducts }}</div>

                <h4 >Wymagane dokumenty </h4>
               

                <template v-for="(option) in documentDircionary">
                  <div  :key="option.name">
                    <CCol sm="12">
                      <input type="checkbox" name="selectedDocuments[]" :value="option.value"
                             v-model="selectedDocuments" :id="option.value"
                             :checked="selectedDocuments.includes(option.value)"/> {{ option.label }}
                    </CCol>
                  </div>
                </template>
                <div>wybrano: {{ selectedDocuments }}</div>


                <h4 >Wymagane pliki dla dostawcy </h4>
                <template v-for="(option) in fileDircionary">
                  <div  :key="option.name">
                    <CCol sm="12">
                      <input type="checkbox" name="selectedFiles[]" :value="option.value" v-model="selectedFiles"
                             :id="option.value" :checked="selectedFiles.includes(option.value)"/> {{ option.label }}
                    </CCol>
                  </div>
                </template>
                <div>wybrano: {{ selectedFiles }}</div>

                <CButton
                  color="primary"
                  @click="submit"
                >
                  Zapisz
                </CButton>
                <CButton
                  
                  color="success"
                  @click="goBack"
                >
                  Cofnij
                </CButton>
              </div>
              <div  : id="tab2">Historia zmian</div>
              <div  : id="tab3">Pliki</div>
              <div  : id="tab4">
                <CRow>
                  <CCol md="12">
                    <CTextarea
                      label="Uwagi do dostawy"
                      placeholder="Uwagi do dostawy"
                      rows="9"
                      v-model.trim="$v.form.deliver_comments.$model"
                    />
                  </CCol>
                </CRow>
                <CRow>
                  <CCol md="12">
                    Podpis odbiorcy delivery_signature
                  </CCol>
                </CRow>
                <CButton
                  color="primary"
                  @click="submit"
                >
                  Zapisz
                </CButton>
                <CButton
                  
                  color="success"
                  @click="goBack"
                >
                  Cofnij
                </CButton>
              </div>
            </div>
          </CForm>
          <br/>
          <div>
            <CModal
              title="Wybierz przewoźnika"
              color="info"
              :show.sync="warningModal"
              size="xl"
              :closeOnBackdrop=true
              @closed="closedEvent"
              :centered="true"
              :onclose="closedEvent"
            >
              <data-table-select
                :fetch-url="datatTableUrl"
                :columns="['id', 'email', 'name', 'surname']"
                :headers="{'id': 'ID','email': 'Email','name': 'Imię','surname': 'Nazwisko'}"
                :routeName="routeName"
              ></data-table-select>
            </CModal>
          </div>
        </CCol>
      </CRow>
    </CCardBody>
  </CCard>
</template>

<script>
import axios from 'axios';
import Vue from 'vue';
import CKEditor from 'ckeditor4-vue';
import Swal from "sweetalert2";
import {validationMixin} from "vuelidate"
import {required, minLength, email, sameAs, helpers} from "vuelidate/lib/validators"
import Datepicker from 'vuejs-datepicker';
import {pl} from 'vuejs-datepicker/dist/locale'
import DataTableSelect from "../../components/DataTableSelect";

export default {
  components: {
    DataTableSelect,
    Datepicker
  },
  data() {
    return {
      warningModal: false,
      datatTableUrl: '',
      routeName: 'carriers',
      modalClasses: ['modal', 'fade'],
      checkedNames: [],
      pl: pl,
      activeItem: 'home',
      form: {
        carrier_id: null,
        carrier_name: null,
        carrier_nip: null,
        carrier_regon: null,
        carrier_email: null,
        carrier_postal_code: null,
        carrier_street: null,
        carrier_city: null,
        carrier_email_to_notification: null,
        driver_id: null,
        comments: null,
        transport_content: null,
        deliver_comments: null,
        carrier_phone: null,
      },
      confirmationTypes: [],
      transportTypes: [],
      drivers: [],
      productDircionary: [],
      documentDircionary: [],
      fileDircionary: [],
      selectedProducts: [],
      selectedDocuments: [],
      selectedFiles: [],
    }
  },
  computed: {
    formString() {
      return JSON.stringify(this.form, null, 4)
    },
    isValid() {
      return !this.$v.form.$invalid
    },
    isDirty() {
      return this.$v.form.$anyDirty
    },
  },
  mixins: [validationMixin],
  validations: {
    form: {
      speed_number: {
        required,
        minLength: minLength(3),
        maxLength: 255
      },
      ...
    }
  },
  methods: {
    closedEvent(){
      alert();
    },
    isActive(menuItem) {
      return this.activeItem === menuItem
    },
    setActive(menuItem) {
      this.activeItem = menuItem
    },
    goBack() {
      this.$router.replace({path: '/tasks'})
    },
    checkIfValid(fieldName) {
      const field = this.$v.form[fieldName]
      if (!field.$dirty) {
        return null
      }
      return !(field.$invalid || field.$model === '')
    },
    store() {
      let self = this;

      axios.post(this.$apiAdress   '/api/tasks?token='   localStorage.getItem("api_token"),
        {
          carrier_id: self.form.carrier_id,
          carrier_name: self.form.carrier_name,
          carrier_nip: self.form.carrier_nip,
          carrier_regon: self.form.carrier_regon,
          carrier_email: self.form.carrier_email,
          carrier_postal_code: self.form.carrier_postal_code,
          carrier_street: self.form.carrier_street,
          carrier_city: self.form.carrier_city,
          carrier_email_to_notification: self.form.carrier_email_to_notification,
          driver_id: self.form.driver_id,
          comments: self.form.comments,
          transport_content: self.form.transport_content,
          deliver_comments: self.form.deliver_comments,
          carrier_phone: self.form.carrier_phone,
          selected_products: self.selectedProducts,
          selected_documents: self.selectedDocuments,
          selected_files: self.selectedFiles,
        })
        .then(function (response) {
          if (response.data.status == 'success') {
            Swal.fire(
              'Sukces',
              'Rekord dodany poprawnie!',
              'success'
            ).then(function () {
              // self.$router.push('/tasks');
            });
          } else {
            Swal.fire(
              'Błąd',
              response,
              'error'
            )
          }
        }).catch(function (error) {
        if (error.response.data.message != '') {
          let errorDetails = ""
          for (let key in error.response.data.errors) {
            errorDetails  = `${error.response.data.errors[key]}<br/>`
          }
          Swal.fire(
            'Błąd',
            errorDetails,
            'error'
          )
          window.scrollTo({top: 0});
        } else {
          Swal.fire(
            'Błąd',
            error,
            'error'
          )
          self.$router.push({path: 'login'});
        }
      });
    },

    submit() {
      let self = this;

      Swal.fire({
        title: "Czy zapisać dane",
        text: "zlecenia w bazie?",
        type: "question",
        showCancelButton: true,
        confirmButtonText: "Tak, zapisz",
        cancelButtonText: "Anuluj",
        reverseButtons: true
      }).then(function (result) {
        if (result.value) {
          self.runSubmit();
        }
      });
    },

    runSubmit() {
      let self = this;
      self.validate();
      if (!this.$v.form.$invalid) {
        this.store();
      }
    },

    validate() {
      this.$v.$touch()
    },

    reset() {
      this.form = this.getEmptyForm()
      this.submitted = false
      this.$v.$reset()
    },

    getEmptyForm() {
      return {
        speed_number: null,
        order_number: null,
        data_start: null,
        data_finish: null,
        address_from: null,
        address_to: null,
        is_neutral_option: null,
        transport_type: null,
        carrier_id: null,
        carrier_name: null,
        carrier_nip: null,
        carrier_regon: null,
        carrier_email: null,
        carrier_postal_code: null,
        carrier_street: null,
        carrier_city: null,
        carrier_email_to_notification: null,
        driver_id: null,
        comments: null,
        transport_content: null,
        deliver_comments: null,
        carrier_phone: null,
        selected_products: null,
        selectedProducts: [],
        selectedDocuments: [],
        selectedFiles: [],
      }
    }
  },
  created: function () {
    this.datatTableUrl = Vue.prototype.$apiAdress   '/api/tasks/carriers-table?token='   localStorage.getItem("api_token");
    let self = this;
    self.setActive('tab1');
    axios.get(this.$apiAdress   '/api/tasks/create?token='   localStorage.getItem("api_token"))
      .then(function (response) {
        self.confirmationTypes = response.data.confirmationTypes;
        self.drivers = response.data.drivers;
        self.transportTypes = response.data.transportTypes;
        self.productDircionary = response.data.productDircionary;
        self.documentDircionary = response.data.documentDircionary;
        self.fileDircionary = response.data.fileDircionary;
      }).catch(function (error) {
      console.log(error);
      self.$router.push({path: '/login'});
    });
  }
}
</script>

and Datatable:

<template>
  <div>
    <div >
      <div >
        <div >
          <input
            v-model="search"
            
            placeholder="Szukaj..."
            type="text"
            @keyup.enter="handleSearch"
          >
          <div >
            <button  type="button" @click.prevent="handleSearch">
              <font-awesome-icon icon="fas fa-search"/>
            </button>
          </div>
        </div>
      </div>

      <div >
        <div >
          <label for="pageOption" >Na stronie</label>
          <select  v-model="perPage" @change="handlePerPage" id="pageOption">
            <option v-for="page in pageOptions" :key="page" :value="page">{{ page }}</option>
          </select>
        </div>
      </div>
    </div>


    <table >
      <thead>
      <tr>
        <th >#</th>
       
        <th v-for="(label, column) in headers" :key="column" @click="sortByColumn(column)" >
          {{ label | columnHead }}
          <span v-if="column === sortedColumn">
                            <font-awesome-icon v-if="order === 'asc'"  icon="fas fa-angle-up" />
                            <font-awesome-icon v-else icon="fas fa-angle-down" />
            </span>
        </th>
        <th >Opcje</th>
      </tr>
      </thead>
      <tbody>
      <tr  v-if="tableData.length === 0">
        <td  :colspan="columns.length   1">Brak danych do wyświetlenia.</td>
      </tr>
      <tr v-for="(data, key1) in tableData" :key="data.id"  v-else>
        <td>{{ serialNumber(key1) }}</td>
        <td v-for="(value, key) in data" style="cursor: pointer">{{ value }}</td>
        <td><button  @click="prepareAddToTask(data.id)">Wybierz</button></td>
      </tr>
      </tbody>
    </table>
    <nav v-if="pagination && tableData.length > 0">
      <ul >
        <li  :>
          <a  href="#" @click.prevent="changePage(currentPage - 1)">Poprzednia</a>
        </li>
        <li v-for="page in pagesNumber" 
            :>
          <a href="javascript:void(0)" @click.prevent="changePage(page)" >{{ page }}</a>
        </li>
        <li  :>
          <a  href="#" @click.prevent="changePage(currentPage   1)">Następna</a>
        </li>
        <span style="margin-top: 8px;"> &nbsp; <i>Wyświetlam {{ pagination.data.length }} z {{ pagination.meta.total }} wyników.</i></span>
      </ul>
    </nav>

  </div>
</template>

<script type="text/ecmascript-6">
import axios from 'axios';
import Vue from 'vue';
import 'vuejs-datatable/dist/themes/bootstrap-4.esm';
import {
  VuejsDatatableFactory,
  IDataFnParams,
  IDisplayHandlerParam,
  ITableContentParam,
  TColumnsDefinition,
  VueDatatable
} from 'vuejs-datatable';

Vue.use(VuejsDatatableFactory, VueDatatable);
import Swal from 'sweetalert2';

export default {
  props: {
    fetchUrl: {type: String, required: true},
    columns: {type: Array, required: true},
    headers: {type: Object, required: true},
    routeName: {type: String, required: true},
    showUrl: {type: String, required: false},
  },
  data() {
    return {
      tableData: [],
      url: '',
      pagination: {
        meta: {to: 1, from: 1}
      },
      offset: 4,
      currentPage: 1,
      perPage: 100,
      sortedColumn: this.columns[0],
      order: 'asc',
      search: '',
      pageOptions: [100, 200, 500, 1000],
      selectedContent: ''
    }
  },
  watch: {
    fetchUrl: {
      handler: function (fetchUrl) {
        this.url = fetchUrl
      },
      immediate: true
    }
  },
  created() {
    console.log(this.fetchUrl);
    return this.fetchData()
  },
  computed: {
    /**
     * Get the pages number array for displaying in the pagination.
     * */
    pagesNumber() {
      if (!this.pagination.meta.to) {
        return []
      }
      let from = this.pagination.meta.current_page - this.offset
      if (from < 1) {
        from = 1
      }
      let to = from   (this.offset * 2)
      if (to >= this.pagination.meta.last_page) {
        to = this.pagination.meta.last_page
      }
      let pagesArray = []
      for (let page = from; page <= to; page  ) {
        pagesArray.push(page)
      }
      return pagesArray
    },
    /**
     * Get the total data displayed in the current page.
     * */
    totalData() {
      return (this.pagination.meta.to - this.pagination.meta.from)   1
    }
  },
  methods: {
    fetchData() {
      let dataFetchUrl = `${this.url}&page=${this.currentPage}&column=${this.sortedColumn}&order=${this.order}&per_page=${this.perPage}&search=${this.search}`
      axios.get(dataFetchUrl)
        .then(({data}) => {
          this.pagination = data
          this.tableData = data.data
        }).catch(error => this.tableData = [])
    },
    /**
     * Get the serial number.
     * @param key
     * */
    serialNumber(key) {
      return (this.currentPage - 1) * this.perPage   1   key
    },
    /**
     * Change the page.
     * @param pageNumber
     */
    changePage(pageNumber) {
      this.currentPage = pageNumber
      this.fetchData()
    },
    /**
     * Sort the data by column.
     * */
    sortByColumn(column) {
      if (column === this.sortedColumn) {
        this.order = (this.order === 'asc') ? 'desc' : 'asc'
      } else {
        this.sortedColumn = column
        this.order = 'asc'
      }
      this.fetchData()
    },
    handleSearch() {
      this.fetchData()
    },
    handlePerPage($event) {
      this.perPage = $event.target.value;
      this.fetchData()
    },

    recordLink(id) {
      return this.routeName   `/${id.toString()}`
    },
    showRecord(id) {
      const recordLink = this.recordLink(id);
      this.$router.push({path: recordLink});
    },
    getDataRecord(id) {
      let self = this;
      axios.get(this.$apiAdress   '/api/carriers/'   id   '/edit?token='   localStorage.getItem("api_token"))
        .then(function (response) {
          self.selectedContent = response.data.record;
          console.log(self.selectedContent); // here is my result @@

        }).catch(function (error) {
        console.log(error);
        self.$router.push({path: '/login'});
      });
    },
    prepareAddToTask(id){
      const copyId = id;
      Swal.fire({
        title: 'Czy na pewno',
        text: "Chcesz dodać tego przewoźnika?",
        type: 'question',
        showCancelButton: true,
        confirmButtonColor: '#d33',
        cancelButtonColor: '#3085d6',
        confirmButtonText: 'Tak!',
        cancelButtonText: 'Anuluj',
        buttonsStyling: true
      }).then((isConfirm) => {
        // now 'this' depends on the lexical enviroment.
        if(isConfirm.value === true) {
          this.getDataRecord(copyId);
        }
      });
    }
    ///
  },
  filters: {
    columnHead(value) {
      return value.split('_').join(' ').toUpperCase()
    }
  },
  name: 'DataTable'
}
</script>

I need show in console log in Main.VUE content which I get from modal / Datatable.

How can I make it?

CodePudding user response:

Since you are new to Vue.js I recommend you reading about props-down and events-up pattern which describes flow of data between Vue components.

  1. Props-down part is describing data flow PARENT -> CHILD, meaning child components should receive data from parent components via props.
  2. Events-up part is describing data flow CHILD -> PARENT, meaning child components should send data to parent components by emitting events.

To get back to your concrete situation, you need to emit an event from Datatable.vue component which you will handle in Main.vue:

In your Datatable.vue you should add this:

 getDataRecord(id) {
      let self = this;
      axios.get(this.$apiAdress   '/api/carriers/'   id   '/edit?token='   localStorage.getItem("api_token"))
        .then(function (response) {
          self.selectedContent = response.data.record;
          self.$emit('content-selected', self.selectedContent);  <-- add this line
        }).catch(function (error) {
        console.log(error);
        self.$router.push({path: '/login'});
      });
  },

Now, in your Main.vue you need to handle the event like this:

<data-table-select
      :fetch-url="datatTableUrl"
      :columns="['id', 'email', 'name', 'surname']"
      :headers="{'id': 'ID','email': 'Email','name': 'Imię','surname': 'Nazwisko'}"
      :routeName="routeName"
      @content-selected="handleContentSelected($event)"  <-- add this line
></data-table-select>

Now, add your function that will handle the event, in your methods add:

handleContentSelected(content) {
     console.log(content); <-- your data should be here
}
  • Related