Reputation: 124
I need to use hyperscript from vue (h function) but I have a problem with conditional class.
Here a reproduction link https://codesandbox.io/p/sandbox/quizzical-albattani-hxk5dd?file=%2Fsrc%2Fcomponents%2Finput.vue%3A14%2C20
in the input.vue view I display the props invalid (next to the input) and in the input itself I declare conditional class
:class="{ '--invalid': invalid }"
If I start writing in the input the props displayed change as expected, but the conditional class is not updated.
Any idea on how to correct this ?
Here my input component
<template>
<div>
invalid: {{ invalid }}
<input
class="theinput"
:class="{ '--invalid': invalid }"
@input="updateValue"
v-model="value"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const props = defineProps(["invalid"]);
const value = ref("");
const emit = defineEmits(["update:value"]);
const updateValue = (event: Event) => {
emit("update:value", (event.target as HTMLInputElement).value);
};
</script>
<style>
.theinput:focus {
outline: none;
}
.--invalid {
border: 1px solid red;
}
</style>
Here how can I call it with render function:
import { h, defineEmits } from "vue";
import theinput from "./input.vue";
const render = (details: any, invalid: any) => {
const emit = defineEmits(["update:value"]);
let copy = { ...details };
copy.invalid = invalid;
return h(theinput, {
...copy,
"update:value": (value: any) => emit("update:value", value),
});
};
export { render };
And this is app.vue
:
<template>
<!-- <theinput :invalid="invalid" @update:value="validate" /> -->
<render-input @update:value="validate"></render-input>
</template>
<script setup>
import theinput from "./components/input.vue";
import { render } from "./components/input.ts";
import { ref, onBeforeMount } from "vue";
let invalid = ref(true);
const validate = (value) => {
invalid.value = value.length < 3;
console.log(invalid.value);
console.log(renderInput.value);
};
onBeforeMount(() => {
defineComponent();
});
let renderInput = ref(null);
const defineComponent = () => {
renderInput.value = render({}, invalid);
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
When the invalid change to false the red border would disappear
EDIT
I fund the solution, in my component declaration
<div>
invalid: {{ invalid }}
<input
class="theinput"
:class="{ '--invalid': invalid }"
@input="updateValue"
v-model="value"
/>
the invalid: {{ invalid }}
mustn't have .value but the :class="{ '--invalid': invalid }"
need it. Both are in template so I don't know if it's a normal behaviour. I asked on the official git repo vue.
Upvotes: 0
Views: 135
Reputation: 41
Using the : syntax for the class binding in the input.vue component:
<template>
<div>
invalid: {{ invalid }}
<input
class="theinput"
:class="{ '--invalid': invalid }"
@input="updateValue"
v-model="value"
/>
</div>
</template>
<script setup lang="ts">
import { ref, watch, defineProps, defineEmits } from "vue";
const props = defineProps<{
invalid: boolean;
}>();
const emit = defineEmits<{
(e: "update:value", value: string): void;
}>();
const value = ref(props.invalid ? "" : null);
watch(
() => props.invalid,
(newValue) => {
if (newValue) {
value.value = "";
}
}
);
const updateValue = (event: Event) => {
emit("update:value", (event.target as HTMLInputElement).value);
};
</script>
<style>
.theinput:focus {
outline: none;
}
.--invalid {
border: 1px solid red;
}
</style>
In this updated version, we are using the : syntax to bind the class attribute, and we are using the watch function to update the value reactive reference when the invalid prop changes.
Here's the updated render function in the input.ts file:
import { h, defineEmits, defineProps } from "vue";
import Theinput from "./input.vue";
const render = (value: any, invalid: any) => {
const emit = defineEmits<{
(e: "update:value", value: string): void;
}>();
let copy = { ...value };
copy.invalid = invalid;
return h(Theinput, {
value: value,
invalid: copy,
"update:value": (v: string
Upvotes: -2