@econnect/webcomponents-library
Documentation
Styleguide
Documentation
Styleguide
  • Getting Started

    • Installation
    • Patch Notes
    • Styleguide
  • Styling

    • e-connect colors
  • UI Components

    • Form

      • Search Field
      • Form Field
      • Forms
    • Filter

      • Filter
      • Search Filter
    • Grid

      • Grid
      • Grid Row
    • Inputs

      • File Input
      • Input Checkbox
      • Input Dropdown
      • Input Date
      • Input Date Time
      • Input Date Time Local
      • Input File
      • Input Label
      • Input Multi Select
      • Input Number
      • Input Radio
      • Input Range
      • Input Select
      • Input Switch
      • Input Slider
      • Input Text
      • Input TextArea
      • Input Time
      • Input Time Range
    • Controls

      • Booleans
      • Button
      • Checkboxes
      • Date Displays
      • Dropdown Lists
      • Text Displays
    • Headers

      • e-header
    • Cards

      • e-card
    • Images

      • Icon
      • Images
      • Flag Image
      • Hamburger
    • Iframe
    • Pager
    • Settings
    • Document Validation
    • Navigation

      • Navigation
      • Navigation Menu
      • Navigation Footer
      • Navigation Button
      • Navigation Button Item
      • Navigation Search Item

Input Date Time v1.0

The <e-input-date-time> component is a component that can be used for datetime inputs.

Usage

An e-input-date-time has attributes that must be provided

<e-input-date-time
  id=""
  value=""
  label=""
  name=""
  placeholder=""
  required=""
  disabled=""
  meta=""
/>

Attributes : e-input-date-time extends e-input

ValueTypeOptionalDefault
valueStringyesnew Date().toDateString()
metaEInputMeta_DateTimeyesnew EInputMeta_DateTime()

Attributes : e-input

ValueTypeOptionalDefault
idStringyes''
valueStringyes''
labelStringyes''
nameStringyes''
placeholderStringyes''
requiredBooleanyesfalse
disabledBooleanyesfalse
metaEInputMetayes{ disabled: false }

Attributes : e-input-meta_date-time

ValueTypeOptionalDefault
disabledBooleanyesfalse
dateDisabledBooleanyesfalse
timeDisabledBooleanyesfalse
requireTimeBooleanyesfalse
minDateRawDateStringyes'1970-01-01'
maxDateRawDateStringyes'9999-12-31'
minTimeHourMinuteTimeStringyes'00:00'
maxTimeHourMinuteTimeStringyes'23:59'

Examples

Below a few interactive examples of e-input-date-time can be found.

Default
<e-input-date-time
  id="dateTimeInputWithOptions"
  value="-"
/>
internal labelled, label='dateTimeInput with Label'
<e-input-date-time
  id="dateTimeInputWithLabel"
  label="dateTimeInput with Label"
  value="-"
/>
separate labelled, label='dateTimeInput with Label'
<div class="input-example-field">
  <e-input-label
    id="dateTimeInputWithExternalLabel"
    value="dateTimeInput with Label"
  />
  <e-input-date-time
    id="dateTimeInputWithExternalLabel"
    value="-"
  />
</div>

Source Code

e-input-date-time.vue
<script lang="ts" setup>
import { computed, ref, watch } from 'vue';
import { useDateFormat } from '@vueuse/core';

import { EInput_DateTime } from 'types/e-input/interfaces/EInput_DateTime';

export type Props = EInput_DateTime;
const props = withDefaults(defineProps<Props>(), {
  value: new Date().toDateString(),
  name: '',
  label: '',
  id: '',
  placeholder: '',
  required: false,
  disabled: false,
  meta: () => {
    return {
      disabled: false,
      dateDisabled: false,
      timeDisabled: false,
      requireTime: false,
      minDate: '1970-01-01',
      maxDate: '9999-12-31',
      minTime: '00:00',
      maxTime: '23:59'
    };
  }
});

const emit = defineEmits<{
  (e: 'blur', event: FocusEvent): void;
  (e: 'keyup.enter', event: KeyboardEvent): void;
  (e: 'update:value', value: string): void;
}>();

const dateInput = ref<HTMLInputElement>();
const timeInput = ref<HTMLInputElement>();

const localValue = ref(new Date(props.value));
const datePattern = ref('YYYY-MM-DD');
const timePattern = ref('HH:mm');

const localDate = useDateFormat(localValue, datePattern);
const localTime = useDateFormat(localValue, timePattern);

const isDisabled = computed(() => props.disabled ?? props.meta?.disabled);
const dateDisabled = computed(() => isDisabled.value ?? props.meta?.dateDisabled);

const minDate = computed(() => props.meta?.minDate || '1970-01-01');
const maxDate = computed(() => props.meta?.maxDate || '9999-12-31');

const dateInputData = computed(() => {
  return {
    id: props.id,
    name: `${props.name}-date`,
    inputValue: localDate.value,
    disabled: dateDisabled.value,
    placeholder: props.placeholder,
    type: 'date',
    pattern: datePattern.value,
    required: props.required,
    min: minDate.value,
    max: maxDate.value
  };
});

const timeDisabled = computed(() => isDisabled.value ?? props.meta?.timeDisabled);
const timeRequired = computed(() => props.meta?.requireTime || false);

const minTime = computed(() => props.meta?.minTime || '00:00');
const maxTime = computed(() => props.meta?.maxTime || '23:59');

const timeInputData = computed(() => {
  return {
    id: `${props.id}-time`,
    name: `${props.name}-time`,
    inputValue: localTime.value,
    disabled: timeDisabled.value,
    placeholder: props.placeholder,
    type: 'time',
    required: timeRequired.value,
    pattern: timePattern.value,
    min: minTime.value,
    max: maxTime.value
  };
});

const stateClasses = computed(() => {
  return {
    required: props.required,
    disabled: isDisabled.value
  };
});

function setLocalDate(event: InputEvent) {
  const target = event.target as HTMLInputElement;
  const isValid = target.checkValidity();

  if (isValid) {
    localValue.value.setFullYear(
      target.valueAsDate.getFullYear(),
      target.valueAsDate.getMonth(),
      target.valueAsDate.getDate()
    );

    emitUpdate();
  }
  // TODO: nullable date support
}

function setLocalTime(event: InputEvent) {
  const target = event.target as HTMLInputElement;
  const isValid = timeInput.value.checkValidity();

  if (isValid) {
    localValue.value.setHours(target.valueAsDate.getHours(), target.valueAsDate.getMinutes(), 0);

    emitUpdate();
  }
}

function updateLocalValue(newValue: string) {
  localValue.value = new Date(newValue);
}

function emitUpdate() {
  const dateTimeString = localValue.value.toString();

  emit('update:value', dateTimeString);
}

watch(
  () => props.value,
  (newValue, oldValue) => {
    if (Date.parse(newValue) && oldValue !== newValue) {
      updateLocalValue(newValue);
    }
  },
  {
    immediate: true
  }
);
</script>

<template>
  <div
    class="e-input-date-time"
    :class="stateClasses"
  >
    <input
      :id="dateInputData.id"
      ref="dateInput"
      class="e-input-date"
      :name="dateInputData.name"
      :value="dateInputData.inputValue"
      :disabled="dateInputData.disabled"
      :placeholder="dateInputData.placeholder"
      :type="dateInputData.type"
      :required="dateInputData.required"
      :pattern="dateInputData.pattern"
      :min="dateInputData.min"
      :max="dateInputData.max"
      @input="setLocalDate"
      @blur="emit('blur', $event)"
      @keyup.enter="emit('keyup.enter', $event)"
    />
    <input
      :id="timeInputData.id"
      ref="timeInput"
      class="e-input-time"
      :name="timeInputData.name"
      :value="timeInputData.inputValue"
      :disabled="timeInputData.disabled"
      :placeholder="timeInputData.placeholder"
      :type="timeInputData.type"
      :required="timeInputData.required"
      :min="timeInputData.min"
      :max="timeInputData.max"
      @input="setLocalTime"
      @blur="emit('blur', $event)"
      @keyup.enter="emit('keyup.enter', $event)"
    />
  </div>
</template>

<style scoped lang="scss">
.e-input-date-time {
  display: flex;
  flex-direction: row;
  color: var(--e-body-font-color);
  gap: 10px;

  input {
    background-color: var(--e-input-background);
    border: none;
    border-radius: 15px;
    color: var(--e-body-font-color);
    display: flex;
    flex: 1 1 auto;
    flex-direction: row;
    font: normal normal normal 16px/20px var(--e-body-font-family);
    gap: 10px;
    height: 50px;
    padding: 15px;

    &::placeholder {
      color: var(--e-gray-300);
    }

    &:focus {
      background-color: var(--e-input-focus-background);
    }

    &:not(:disabled) {
      cursor: pointer;

      ::-webkit-calendar-picker-indicator {
        cursor: pointer;
      }
    }

    &:user-invalid,
    &:out-of-range {
      color: var(--e-red);
    }

    &:disabled {
      color: var(--e-disabled);

      ::-webkit-calendar-picker-indicator {
        cursor: not-allowed;
        color: var(--e-disabled);
        //TODO: task#11629 replace with e-icon for state?
      }
    }
  }

  &[required] {
    + label::after {
      content: '*';
      padding-left: 2px;
      color: var(--e-required);
      font-weight: bold;
    }
  }
}
</style>
Last Updated:: 12/16/24, 2:58 PM
Contributors: Marcel Lommers
Prev
Input Date
Next
Input Date Time Local