Home > OS >  Error when attempting to disable Navigation Buttons in VueJs
Error when attempting to disable Navigation Buttons in VueJs

Time:10-20

In my ticket processing application I currently have a back and forward button contained in my TicketRunner.vue Component, I would like to change it so that these buttons only appear if I have an associated case file, for which I've used V-If:

TicketRunner.Vue

<div  v-if='!currentTicketCaseFiles.length'>
    <div >
      <b-button
        @click.prevent="navGoPrev()"
        :disabled="currentStepIndex === 0 || navWaiting"
        size="is-medium"
      >
    </div>


   export default {
  name: 'TicketRunner',

  mixins: [NavStepsByIndexMixin()],

  components: {
    StagePresenter,
    CaseFilesStage,
    ParticipantsStage,
    AttachmentsStage,
    CaseFilesRunner,
    TicketContextButtons,
  },

  data: function() {
    return {
      firstComponentsInitialization: true,
      loadingConfirm: false,
      confirmationModalActive: false,
      confirmationSucceeded: undefined
    }
  },

  props: {
    ticketId: {
      type: Number,
      required: true,
    },
  },

  provide() {
    return  {
      contextButtons: {
        capture: (name, callback, title) => this.$refs['contextButtons'].captureButton(name, callback, title),
        release: (name) => this.$refs['contextButtons'].releaseButton(name),
        enable: (name) => this.$refs['contextButtons'].enableButton(name),
        disable: (name) => this.$refs['contextButtons'].disableButton(name),
      },
    };
  },

  computed: {
    ...mapGetters(['currentTicket', 'ticketCaseFiles', 'allCurrentTicketAttachments', 'currentTicketCaseFileNotAssociated',
      'currentRequesterType', 'currentTicketStage', 'lastCaseFile']),
    caseFiles() {
      return this.ticketCaseFiles(this.ticketId);
    },
    ticketHasAttachments() {
      return this.allCurrentTicketAttachments.length > 0;
    },
    isTicketAssociatedWithCaseFile() {
      return !this.currentTicketCaseFileNotAssociated;
    },
    isFirstNavInitializationInProgress() {
      return !this.navReady && this.firstComponentsInitialization;
    },
    isShowAttachmentsStep() {
      return this.ticketHasAttachments && this.currentRequesterType !== 'unknown' &&
               (this.isFirstNavInitializationInProgress || this.isTicketAssociatedWithCaseFile)
    },
    isCurrentTicketResolved() {
      return this.currentTicket.status === 'resolved';
    },
    islastStep() {
      return this.navLastStep() && this.lastCaseFile; 
    }
  },

  watch: {
    ticketId(){
      this.navigator.reset();
    },
    navReady() {
      this.moveForwardIfReady();
      this.firstComponentsInitialization = false;
    }
  },

  methods: {
    ...mapActions(['confirmTicket']),

    moveForwardIfReady() {
      if (this.navigator.currentIndex === 0 && this.firstComponentsInitialization) {
        let steps = 0
        const step_names = ['case_files_stage']
        for(const [_idx, name] of step_names.entries()) {
          const ref_name = `step[${name}]`;
          if (this.$refs.hasOwnProperty(ref_name) && this.$refs[ref_name].navReady) {
            steps  = 1
          } else {
            break
          }
        }
        this.navigator.currentIndex  = steps
      }
    },

    confirm() {
      this.$buefy.dialog.confirm({
        message: this.t('tickets.stages.confirmation.simplified_confirm_reply'),
        onConfirm: () => this.confirmStep()
      })
    },

    async confirmStep() {
      this.loadingConfirm = true;
      const promise = this.confirmTicket(this.ticketId);

      return promise.then((response) => {
        this.confirmationModalActive = true;
        this.confirmationSucceeded = true;
        return true; // true is correct here. for goNext it makes parent to stay on on the current step
      }).catch(() => {
        this.confirmationModalActive = true;
        this.confirmationSucceeded = false;
        return true; // true is correct here. for goNext it makes parent to stay on on the current step
      }).finally(() => this.loadingConfirm  = false);
    },
  },
};

I then receive the following Console Error:

[Vue warn]: Property or method "currentTicketCaseFiles" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.

I know that "!currentTicketCaseFiles.length" works successfully in the Component CaseFilesStage.vue, which makes me believe I should somehow connect the two? But importing it doesn't seem right to me either. I'm not quite sure how to tackle this issue as I'm quite new at VueJS, and would be happy for any pointers. I'll attach the CaseFilesStage.vue Component below.

CaseFilesStage.vue

<template>
  <div >
    <div >
      <template v-if="!currentTicket.spamTicket">
        <b-field>
          <b-input
              v-model="filter"
              :loading="loading"
              :placeholder="t('tickets.stages.case_files.search.tooltip')"
              v-on:keyup.enter.native="searchCaseFiles"
              type="search"
              icon="search"
              :
          />
        </b-field>
        <template v-if="foundCaseFiles.length">
          <h4 >{{ t('tickets.stages.case_files.search.table_title') }}</h4>
          <CaseFilesSearchTable
              :case-files="foundCaseFilxes"
              :found-by-data-points="foundCaseFilesByParticipant"
              :show-header="true"
              v-slot="cf">
            <b-checkbox v-if="cfBelongsToCurrentTicket(cf.id)" :disabled="true" :value="true"></b-checkbox>
            <b-checkbox v-else @input="onFoundCaseFile(cf.id, $event)"></b-checkbox>
          </CaseFilesSearchTable>
        </template>
        <div v-else-if="lookupStatus === 'notFound'">
          {{ t('tickets.stages.case_files.search.not_found') }}
          <!-- display button here if above is activated -->
        </div>
      </template>
    </div>
    <template v-if='currentTicketCaseFiles.length'>
      <h4 >{{ t('tickets.stages.case_files.table_title') }}</h4>
      <CaseFilesTable :case-files="currentTicketCaseFiles" :show-header="true" v-slot="cf">
        <DeleteButton
          :model-id="cf.id"
          modelName="CaseFile" >
        </DeleteButton>
      </CaseFilesTable>
    </template>
  </div>
</template>

<script>

import CaseFilesTable from '../tables/CaseFilesTable';
import CaseFilesSearchTable from '../tables/CaseFilesSearchTable';
import DeleteButton from '../../../../shared/components/controls/DeleteButton';

import { mapGetters, mapActions } from 'vuex';
import { mapServerActions } from "../../../../../../_frontend_infrastructure/javascript/lib/crudvuex_new";

export default {
  name: 'CaseFilesStage',

  data() {
    return {
      lookupStatus: 'waitingInput',
      filter: '',
      waiting: {},
      foundCaseFiles: [],
      foundCaseFilesByParticipant: {}
    };
  },

  components: {
    CaseFilesTable,
    CaseFilesSearchTable,
    DeleteButton
  },

  computed: {
    ...mapGetters(
      ['currentTicketCaseFiles', 'currentTicketCaseFileNotAssociated', 'currentTicket', 'showAttachmentsPreview']
    ),
    loading() {
      return this.lookupStatus === 'waitingServer';
    },

    allCaseFilesMix(){
      this.currentTicketCaseFiles   this.foundCaseFiles
    },

    foundCaseFilesEx() {
      return this.foundCaseFiles.filter((x) => !this.cfBelongsToCurrentTicket(x.id))
    },

    checkboxValue() {
      if(!this.currentTicketCaseFileNotAssociated) {
        return null;
      }

      return true;
    },

    navReady() {
      return this.currentTicket.spamTicket || this.currentTicketCaseFiles.length > 0 || this.checkboxValue;
    },
    markSpam: {
      get: function() {
        return this.currentTicket.spamTicket
      },
      set: function(val) {
        return this.updateTicket([this.currentTicket.id, { spam_ticket: val }]);
      },
    }

  },

  methods: {
    ...mapActions(['updateTicket']),
    ...mapServerActions(['createCaseFile', 'deleteCaseFile']),

    cfBelongsToCurrentTicket(id){
      return this.currentTicketCaseFiles.map((x) => x.caseFileId).includes(id);
    },

    cantAssignCaseFileCheckbox(isChecked){
      if(isChecked) {
         this.createCaseFile({ isCfNotAssociated: true });
      } else {
         this.deleteCaseFile(this.currentTicketCaseFileNotAssociated);
      }
    },

    onFoundCaseFile(id, useIt){
      console.log("onFoundCaseFile: ", id, useIt);

      if(useIt) {
         this.createCaseFile({ caseFileId: id });
      } else {
         this.deleteCaseFile(this.currentTicketCaseFiles.find({ caseFileId: id }));
      }
    },

    searchCaseFiles() {
      const newData = this.filter;

      if (newData.length < 3) { // TODO: some smarter condition here
        this.foundCaseFiles = [];
        this.lookupStatus = 'waitingInput';
        return;
      }

      this.lookupStatus = 'waitingServer';
      this.$axios.get('case_files', { params: { "case_files.filter" : newData } })
        .then((response) => {
          this.foundCaseFiles = response.data.caseFilesSearchResult.caseFiles;
          this.foundCaseFilesByParticipant = response.data.caseFilesSearchResult.foundByPrivateInfo;
          if(this.foundCaseFiles.length > 0) {
            this.lookupStatus = 'success';
          } else {
            this.lookupStatus = 'notFound';
          }
        }).catch(() => this.lookupStatus = 'error');
    }
  },
};
</script>

</style>

CodePudding user response:

Add this to your TicketRunner.vue Component script:

computed: {
  ...mapGetters(['currentTicketCaseFiles'])
}
  • Related