@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 File v1.0

The <e-input-file> component is a component that can be used for .

Usage

An e-input-file has attributes that must be provided,

<e-input-file
  id="input_id"
/>

Attributes

ValueTypeOptionalDefault
idStringno
valueStringyes''
placeholderStringyes''
labelStringyes''
requiredBooleanyesfalse
disabledBooleanyesfalse
metaEInputMeta_Fileyes'default'

Meta Attributes

ValueTypeOptionalDefault
accept[ String, String[] ]yes''
override_nameStringyes''
autoCompleteBooleanyes''
disabledBooleanyes''
multipleBooleanyes''
filesFile[]yes'default'

Events

ValueOptionalparams
blurno[ event: FocusEvent ]
keyup.enterno[ event: KeyboardEvent ]
update:valueno[ value: FileList ]

Examples

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

Default
<e-input-file
  id="input_id"
/>
Labelled, label='FileInput with Label'
<e-input-file
  id="input_with_label_id"
/>

Source Code

e-input-file.vue
<script setup lang="ts">
import { computed, ref, unref } from 'vue';
import { isEmpty, join } from 'lodash-es';
import { useElementHover } from '@vueuse/core';

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

import EIcon from '../e-icon/e-icon.vue';

export type Props = EInput_File;
const props = withDefaults(defineProps<Props>(), {
  value: '',
  label: '',
  placeholder: '',
  required: false,
  disabled: false,
  meta: () => {
    return {
      autoComplete: false,
      disabled: false,
      accept: '',
      files: [],
      multiple: false,
      override_name: ''
    };
  }
});

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

const input = ref<HTMLInputElement>();
const inputContainer = ref<HTMLDivElement>();

const isHovered = useElementHover(inputContainer);
const isFocused = ref(false);

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

const showPlaceholder = computed(() => isEmpty(props.label) && isEmpty(props.value));

const displayText = computed(() => props.label || props.value || props.placeholder || '');

const stateClasses = computed(() => {
  return {
    disabled: isDisabled.value,
    focused: isFocused.value,
    placeholder: showPlaceholder.value
  };
});

const accept = computed(() => {
  switch (typeof props.meta?.accept) {
    case 'string':
      return props.meta?.accept ?? '';
    case 'object':
      return props.meta?.accept?.join(', ');
    default:
      return null;
  }
});

const multiple = computed(() => props.meta?.multiple);

const iconState = computed(() => {
  const states: string[] = [];

  if (isDisabled.value) {
    return 'disabled';
  }

  if (isFocused.value) {
    states.push('focused');
  }

  if (unref(isHovered)) {
    states.push('hovered');
  }

  if (states.length > 0) {
    return join(states, '-');
  } else {
    return 'default';
  }
});

async function updateValue(event: Event) {
  const target = event.target as HTMLInputElement;
  const files = target.files;

  emitUpdate(files);
}

function emitUpdate(files: FileList) {
  emit('update:value', files);
}

function setFocus(newValue: boolean) {
  isFocused.value = newValue;
}
</script>

<template>
  <label
    ref="inputContainer"
    class="e-input-file"
    :class="stateClasses"
    :for="id"
    :title="displayText"
    tabindex="0"
    @focusin="setFocus(true)"
    @focusout="setFocus(false)"
  >
    <e-icon
      :icon="['upload']"
      :icon-state="iconState"
      style-key="input"
    />

    <span v-text="displayText" />

    <input
      :id="id"
      ref="input"
      type="file"
      :name="id"
      :accept="accept"
      :disabled="isDisabled"
      :multiple="multiple"
      :required="required"
      @input="updateValue"
      @blur="emit('blur', $event)"
      @keyup.enter="emit('keyup.enter', $event)"
    />
  </label>
</template>

<style scoped lang="scss">
input[type='file'] {
  display: none;
}

.e-input-file {
  background-color: var(--e-input-background);
  border: 2px solid transparent;
  border-radius: 15px;
  padding: 14px;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  cursor: pointer;

  .e-icon {
    max-width: 24px;
  }

  span {
    color: var(--e-text-input-font-color);
    font-family: var(--e-text-input-font-family);
    font-size: var(--e-text-input-font-size);
    font-weight: var(--e-text-input-font-weight);
    line-height: var(--e-text-input-font-line-height);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  &:hover,
  &:focus,
  &.focused {
    background-color: var(--e-input-focus-background);

    span {
      color: inherit;
    }
  }

  &:focus,
  &.focused {
    border-color: var(--e-secondary);

    span {
      color: var(--e-secondary);
    }
  }

  &:hover {
    border-color: var(--e-navigation-button-font-hover-color);

    span {
      color: var(--e-navigation-button-font-hover-color);
    }
  }

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

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

    span {
      color: var(--e-disabled);
    }
  }

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