0

Precondition: Vue3 + typescript + vue-class-component Im trying to append a dynamic created div to a div element inside of the template tag on focusin on an input template Element.

I tried two ways to do that:

1. I tried to get the template div element by its id and append the dynamic created div to it on focusin of the input element:

<template>
  <div id="testId" ref="errorDiv">
    <input type="text" @focusin="handleFocusIn"/>
  </div>
</template>

<script lang="ts">
  import { Vue } from 'vue-class-component';

  export default class HelloWorld extends Vue {

    public handleFocusIn = (): void => {
      
      this.appendDivById(); // <----- not working when using this component multiple times on samae page
      
    }

    private appendDivById() : void {
      let errorDivRef = document.getElementById('testId') as HTMLDivElement

      var div = document.createElement("div") as HTMLDivElement;
      div.innerHTML = "Hello World";

      errorDivRef.append(div);
    }

  }
</script>

That seems to work but when you are using that component multiple times on the same page all elements have the same Id and every dynamic created div will be appended to the first div.

2. I tried to get the template div element by its reference and append the dynamic created div to it:

<template>
  <div id="testId" ref="errorDiv">
    <input type="text" @focusin="handleFocusIn"/>
  </div>
</template>

<script lang="ts">
  import { Vue } from 'vue-class-component';

  export default class HelloWorld extends Vue {

    declare $refs: {
      errorDiv: HTMLDivElement;
    };

    // errorDiv = ref<HTMLDivElement | null>(null); // <----- errorDiv.value is always null even in mounted

    public handleFocusIn = (): void => {
      
      this.appendDivByRef(); // <----- not working $refs.errorDiv always undefined
      
    }

    public mounted() { // <----- working but wrong time
      var div = document.createElement("div") as HTMLDivElement;
      div.innerHTML = "Hello World";

      this.$refs.errorDiv.append(div); // <----- $refs.errorDiv not undefined
    }

    private appendDivByRef() : void {
      var div = document.createElement("div") as HTMLDivElement;
      div.innerHTML = "Hello World";

      this.$refs.errorDiv.append(div); // <----- not working $refs.errorDiv always undefined
    }

  }
</script>

This is not working because the reference is always undefined. If I have understood correctly, you can only access a reference in the mounted function, but this is the wrong time.

The Option using v-for for dynamic lists is not the right in this case because I want to append exact one element.

Am I on the right track or is this approch completly wrong?

3
  • I may be missing something, but have you considered adding the div element to the template and then using v-if to show/hide when needed? If you must add it programmatically, you should check if the div element already exists and remove it prior to adding a new div. Commented Mar 3, 2023 at 15:57
  • You can access your div element like this on setup: const errorDiv = ref<HTMLElement | null>(null); errorDiv will be populated on mount. $refs is no longer used in Vue3 Commented Mar 3, 2023 at 16:13
  • Thank you very much for your comment. I simply tried to add a div to the template on click. This is just a a feasibility study without any relation to reality. const errorDiv = ref<HTMLElement | null>(null); doesnt work either. The errorDiv stays undefined. I think the only sensible solution is to switch to composition api and forget the old class component. Would you agree? Commented Mar 6, 2023 at 12:07

1 Answer 1

0

I think the best way to implement stuff like that is to use the modern composition api and forget the old class components.

A working implementation would be:

<template>
  <div id="testId" ref="errorDiv">
    <input type="text" @focusin="handleFocusIn"/>
  </div>
</template>

<script setup lang="ts">
  import { ref } from 'vue';

  const errorDiv = ref<HTMLDivElement>();
  
  function handleFocusIn(): void {
    var div = document.createElement("div") as HTMLDivElement;
    div.innerHTML = "Hello World"
    errorDiv.value?.append(div);
  }

</script>
Sign up to request clarification or add additional context in comments.

1 Comment

Did you try switching to vue-facing-decorator to use your class components in Vue 3? That’s the suggested successor to vue-property-decorator and vue-class-component now

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.