ldc-crm/resources/ts/bo/components/InputTextAutoComponent.vue

105 lines
2.7 KiB
Vue
Raw Permalink Normal View History

2023-06-15 12:28:05 +02:00
<template>
2025-08-04 14:50:03 +02:00
<div>
<WordCounter
:id="id"
class="ck-word-count"
/>
<textarea
ref="textarea"
:id="id"
:class="{'form-control': true, [classPath]: !!classPath, 'is-invalid': errors.methods.parseValidationInput('content', allErrors)}"
:name="name"
:aria-describedby="ariaDescribedby"
:placeholder="placeholder"
:required="required"
@input="styleElement(checkInput())"
@blur="onBlur"
v-model="value"
rows="5"
/>
</div>
2023-06-15 12:28:05 +02:00
</template>
<script lang="ts" setup>
import { computed, nextTick, onBeforeMount, onMounted, ref, useAttrs } from "vue";
2023-06-15 12:28:05 +02:00
import WordCounter from "./WordCounterComponent.vue";
import errors from "./../../modules/errors";
2023-06-15 12:28:05 +02:00
defineOptions({
name: "InputTextAutoComponent"
});
// * ATTRIBUTES
const attrs = useAttrs();
// * REFS
const textarea = ref<HTMLTextAreaElement|null>(null);
// * DATA
/** Hack to set the id for wordCounterComponent. */
const id = ref<string>(JSON.parse(String(attrs.json ?? "{}")).id);
const classPath = ref<string>("");
const name = ref<string>("");
const placeholder = ref<string>("");
const ariaDescribedby = ref<string>("");
const value = ref<string>("");
const required = ref<boolean>(true);
const allErrors = ref<LaravelValidationErrors>({});
2023-06-15 12:28:05 +02:00
// * COMPUTED
const isUsedWithProps = computed<boolean>(() => attrs.json === undefined);
onBeforeMount(() => {
if (isUsedWithProps.value) {
throw new Error("this component requires json");
}
2023-06-15 12:28:05 +02:00
});
// * LIFECYCLE
onMounted(() => {
const json = String(attrs.json ?? "{}"),
data = JSON.parse(json);
if (!isUsedWithProps.value) {
id.value = String(data.id);
classPath.value = String(data.class);
name.value = String(data.name);
placeholder.value = String(data.placeholder);
ariaDescribedby.value = String(data.ariaDescribedby);
value.value = String(data.value);
required.value = data.required;
textarea.value?.setAttribute("style", "height:1rem;overflow-y:hidden;");
allErrors.value = data.errors;
}
nextTick(() => {
styleElement(checkInput());
});
});
// * METHODS
/** When the textarea get the focus. */
function onBlur() {
const el = checkInput();
/** Remove every new line char */
// el.value = el.value.replace(/[\n\r]/g, "");
nextTick(() => {
styleElement(el);
});
}
/** Check if the element is an HTMLTextAreaElement. */
function checkInput(): HTMLTextAreaElement {
const el = textarea.value;
if (!el) {
throw new Error("undefined textarea element");
}
return el;
2023-06-15 12:28:05 +02:00
}
/** Style the textarea element. */
function styleElement(el: HTMLTextAreaElement): void {
el.style.height = "auto";
el.style.height = `${el.scrollHeight}px`;
}
</script>