Skip to content
Snippets Groups Projects
FeatureExtraForm.vue 14.3 KiB
Newer Older
  <div
    v-if="field && field.field_type === 'char'"
    :class="['field', { disabled }]"
Florent Lavelle's avatar
Florent Lavelle committed
      :class="{ required: field.is_mandatory }"
      type="text"
      :name="field.name"
Florent Lavelle's avatar
Florent Lavelle committed
      :required="field.is_mandatory"
Florent Lavelle's avatar
Florent Lavelle committed
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  <div
    v-else-if="field && field.field_type === 'list'"
    :class="['field', { disabled }]"
Florent Lavelle's avatar
Florent Lavelle committed
      :class="{ required: field.is_mandatory }"
    <Dropdown
      :options="field.options"
      :selected="selected_extra_form_list"
      :selection.sync="selected_extra_form_list"
Florent Lavelle's avatar
Florent Lavelle committed
      :required="field.is_mandatory"
      :clearable="true"
Florent Lavelle's avatar
Florent Lavelle committed
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  <div
    v-else-if="field && field.field_type === 'pre_recorded_list'"
    :class="['field', { disabled }]"
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <Multiselect
      v-model="selectedPrerecordedValue"
      :options="
        selectedPrerecordedListValues[field.options[0]] ? selectedPrerecordedListValues[field.options[0]] : []
      "
      :options-limit="10"
      :allow-empty="!field.is_mandatory"
      track-by="label"
      label="label"
      :reset-after="false"
      select-label=""
      selected-label=""
      deselect-label=""
      :searchable="true"
      :placeholder="'Recherchez une valeur de la liste pré-définie ...'"
      :show-no-results="true"
      :loading="loadingPrerecordedListValues"
      :clear-on-select="false"
      :preserve-search="false"
      @search-change="search"
      @select="selectPrerecordedValue"
    >
      <template slot="clear">
        <div
          v-if="selectedPrerecordedValue"
          class="multiselect__clear"
          @click.prevent.stop="clearPrerecordedValue"
        >
          <i
            class="close icon"
            aria-hidden="true"
          />
        </div>
      </template>
      <span slot="noResult">
        Aucun résultat.
      </span>
      <span slot="noOptions">
        Saisissez les premiers caractères ...
      </span>
    </Multiselect>
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>

  <div
    v-else-if="field && field.field_type === 'multi_choices_list'"
    :class="['field', { disabled }]"
    <label
      v-if="displayLabels"
      :for="field.name"
      :class="{ required: field.is_mandatory }"
    >
      {{ field.label }}
    </label>
    <div class="checkbox_list">
      <div
        v-for="option in field.options"
        :key="option"
        class="ui checkbox"
        <input
          :id="option"
          type="checkbox"
          :checked="field.value && field.value.includes(option)"
          :name="option"
          @change="selectMultipleCheckbox"
        >
        <label :for="option">
          {{ option }}
        </label>
      </div>
    </div>
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  </div>

  <div
    v-else-if="field && field.field_type === 'integer'"
    :class="['field', { disabled }]"
Florent Lavelle's avatar
Florent Lavelle committed
      :class="{ required: field.is_mandatory }"
      <!-- //* si click sur fléche dans champ input, pas de focus, donc pas de blur, donc utilisation de @change -->
        type="number"
        :name="field.name"
Florent Lavelle's avatar
Florent Lavelle committed
        :required="field.is_mandatory"
Florent Lavelle's avatar
Florent Lavelle committed
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  <div
    v-else-if="field && field.field_type === 'boolean'"
    :class="['field', { disabled }]"
  >
    <div :class="['ui checkbox', { disabled }]">
        :id="field.name"
        type="checkbox"
        :checked="field.value"
        :name="field.name"
        @change="updateStore_extra_form"
        {{ displayLabels ? field.label : '' }}
  <div
    v-else-if="field && field.field_type === 'date'"
    :class="['field', { disabled }]"
Florent Lavelle's avatar
Florent Lavelle committed
      :class="{ required: field.is_mandatory }"
      type="date"
      :name="field.name"
Florent Lavelle's avatar
Florent Lavelle committed
      :required="field.is_mandatory"
      @change="updateStore_extra_form"
Florent Lavelle's avatar
Florent Lavelle committed
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  <div
    v-else-if="field && field.field_type === 'decimal'"
    :class="['field', { disabled }]"
Florent Lavelle's avatar
Florent Lavelle committed
      :class="{ required: field.is_mandatory }"
        :id="field.name"
Florent Lavelle's avatar
Florent Lavelle committed
        :required="field.is_mandatory"
Florent Lavelle's avatar
Florent Lavelle committed
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
  <div
    v-else-if="field && field.field_type === 'text'"
    :class="['field', { disabled }]"
Florent Lavelle's avatar
Florent Lavelle committed
      :class="{ required: field.is_mandatory }"
Florent Lavelle's avatar
Florent Lavelle committed
      :required="field.is_mandatory"
Florent Lavelle's avatar
Florent Lavelle committed
    <ul
      v-if="field.is_mandatory && error"
      :id="`errorlist-extra-form-${field.name}`"
      class="errorlist"
    >
      <li>
        {{ error }}
      </li>
    </ul>
import { mapState, mapActions, mapMutations } from 'vuex';
import Multiselect from 'vue-multiselect';
import { isEqual } from 'lodash';
import Dropdown from '@/components/Dropdown.vue';
  name: 'FeatureExtraForm',
Timothee P's avatar
Timothee P committed
  props: {
    field: {
      type: Object,
      default: null,
    },
    isConditionalField: {
      type: Boolean,
      default: false,
Timothee P's avatar
Timothee P committed
    }
  },
Florent Lavelle's avatar
Florent Lavelle committed
  data() {
    return {
      prerecordedListSearchQuery: null,
      loadingPrerecordedListValues: false,
      selectedPrerecordedValue: null,
      selectedMultipleCheckbox: [],
    ...mapState('feature-type', [
      'selectedPrerecordedListValues'
    ]),
    ...mapState('feature', [
      'extra_forms',
    ]),
        return this.field.value || '';
      },
      set(newValue) {
        //* set the value selected in the dropdown
        if (this.isConditionalField) {
          this.$emit('update:condition-value', newValue);
        } else {
          const newExtraForm = this.field;
          newExtraForm['value'] = newValue;
          this.$store.commit('feature/UPDATE_EXTRA_FORM', newExtraForm);
        }
      return this.$route.name === 'editer-signalement' || this.$route.name === 'ajouter-signalement' || this.$route.name === 'editer-attribut-signalement';
    },

    disabled () {
      return this.field.disabled;
Florent Lavelle's avatar
Florent Lavelle committed
  watch: {
    'field.value': function(newValue, oldValue) {
      // In fast edition, prerecordedlist is not updated, thus the value stay the same
      // in this case we renitialize the field. This doesn't impact usual behavior if user reselect the same option
      if (this.field) {
        if (this.field.field_type === 'pre_recorded_list') {
          // if both values are defined but their values changed, value in form should be updated
          if (newValue && oldValue && newValue.label !== oldValue.label
          // if any of them is undefined, the form value should be updated, because in this case the value changed
          // otherwise (if they are both undefined) the watcher would not called, thus we don't need to prevent this case
          || !newValue || !oldValue)
          {
            this.initPrerecordedXform();
          }
        } else if (this.field.field_type === 'multi_choices_list') {
          // if array values changed, value in form should be updated, otherwise at edition in fast browsing mode, it would overide current value with previous value loaded at component creation
          if (isEqual(newValue, oldValue)){
            this.initMultipleCheckboxXform();
          }
        this.error = null;
    prerecordedListSearchQuery(newValue) {
      this.loadingPrerecordedListValues = true;
      this.GET_SELECTED_PRERECORDED_LIST_VALUES({
        name: this.field.options[0],
        pattern: newValue
      })
        .then(() => {
          this.loadingPrerecordedListValues = false;
        })
        .catch(() => {
          this.loadingPrerecordedListValues = false;
        });
    }
      if (this.field.field_type === 'pre_recorded_list') {
        this.initPrerecordedXform();
      } else if (this.field.field_type === 'multi_choices_list') {
        this.initMultipleCheckboxXform();
    // autoset field to false if is a boolean, since user doesn't need to select it, when false value is expected
    if (this.field.field_type === 'boolean' && (this.field.value === undefined || this.field.value === null)) {
      this.updateStore_extra_form(false);
    ...mapActions('feature-type', [
      'GET_SELECTED_PRERECORDED_LIST_VALUES'
    ]),
    ...mapMutations('feature', [
      'UPDATE_EXTRA_FORM',
      'SET_EXTRA_FORMS',
    initMultipleCheckboxXform() {
      this.selectedMultipleCheckbox = this.field.value || [];
      const { options, value } = this.field;
      this.loadingPrerecordedListValues = true;
      this.GET_SELECTED_PRERECORDED_LIST_VALUES({
        name: options[0],
        pattern: ''
      })
        .then(() => {
          this.loadingPrerecordedListValues = false;
        })
        .catch(() => {
          this.loadingPrerecordedListValues = false;
        });
      if (value) {
        this.selectedPrerecordedValue = { label: value.label ? value.label : value };
      } else {
        this.selectedPrerecordedValue = null;
      if (this.field) {
        if (evt && evt.target) { // if called from the template
          if (this.field.field_type === 'boolean') {
            newValue = evt.target.checked; //* if checkbox, use "checked"
          } else {
            newValue = evt.target.value;
          }
        } else if (this.field.field_type === 'multi_choices_list') { // special case where the value is stored in the state
          newValue = this.selectedMultipleCheckbox;
        } else { // if the newValue was sent directly
          newValue = evt;
        }
        //* set the value selected
        if (this.isConditionalField) {
          this.$emit('update:condition-value', newValue);
          this.UPDATE_EXTRA_FORM({ ...this.field, ['value']: newValue });
Florent Lavelle's avatar
Florent Lavelle committed

    checkForm() {
      let isValid = true;
      if (this.field && this.field.is_mandatory && !this.field.value) {
Florent Lavelle's avatar
Florent Lavelle committed
        isValid = false;
        this.error = 'Ce champ est obligatoire';
      } else {
        this.error = null;
      }
      return isValid;
    search(text) {
      this.prerecordedListSearchQuery = text;
    },

    selectPrerecordedValue(e) {
      this.selectedPrerecordedValue = e;
      this.prerecordedListSearchQuery = null;
      this.updateStore_extra_form({ target: { value:  this.selectedPrerecordedValue } });
    },
    
    clearPrerecordedValue() {
      this.selectedPrerecordedValue = null;
      this.prerecordedListSearchQuery = null;
      this.updateStore_extra_form({ target: { value:  null } });
    },

    selectMultipleCheckbox(e) {
      const { checked, name } = e.target;
      if (checked) {
        this.selectedMultipleCheckbox.push(name);
      } else {
        this.selectedMultipleCheckbox = this.selectedMultipleCheckbox.filter((el) => el !== name);
      }
      this.updateStore_extra_form();
    },
Florent Lavelle's avatar
Florent Lavelle committed
</script>
Florent Lavelle's avatar
Florent Lavelle committed

<style lang="less" scoped>
Florent Lavelle's avatar
Florent Lavelle committed
label.required:after {
	content: ' *';
	color: rgb(209, 0, 0);
}
.checkbox_list {
  display: flex;
  flex-direction: column;
  .ui.checkbox {
    margin: .5rem;
    font-weight: normal;
  }
<style>
/* keep placeholder width when opening dropdown */
.multiselect {
  width: 305px;
}
/* keep font-weight from overide of semantic classes */
.multiselect__placeholder, .multiselect__content, .multiselect__tags  {
  font-weight: initial !important;
}
/* keep placeholder eigth */
.multiselect .multiselect__placeholder {
  margin-bottom: 9px !important;
  padding-top: 1px;
}
/* keep placeholder height when opening dropdown without selection */
input.multiselect__input {
  padding: 3px 0 0 0 !important;
}
/* keep placeholder height when opening dropdown with already a value selected */
.multiselect__tags .multiselect__single {
  padding: 1px 0 0 0 !important;
  margin-bottom: 9px;
}
Florent Lavelle's avatar
Florent Lavelle committed
</style>