Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue 3 Composition API...how to replace getElementById

I wrote the following in Vue 3 Composition API.

If you look on the "onMounted" I'm attaching an event listener to the window to keep the status box to the bottom of the screen. I'm using absolute position and bottom 0.

I'm wondering if I can make this more "Vue" by replacing the getElementById? I tried refs but it's not working.

Any suggestions or should I leave well enough alone?

Thanks

<template>
  <div>
    <transition name="toast">
      <div id="slide" class="slide-modal" v-if="statuses.length">
        <div class="clear-notifications" @click='clearAllNotifications()'>Clear all notifications</div>
        <div v-for="status in statuses" :key="status.id" class="status-div">
          <div>{{ status.text }}</div>
          <div @click="closeStatus(status)"><span class="-x10-cross"></span></div>
        </div>
      </div>
    </transition>
  </div>
</template>

<script lang="ts">
  import { defineComponent, ref, computed, watch, onMounted } from "vue";
  import { useStore } from "../model/DataStore";
  export default defineComponent({ 
    setup() {
    const store = useStore();

    const statuses = ref([]);

    const statusMessage = computed(() => store.state.statusMessage);
    function  addStatus(newMessage) {

          statuses.value.push({
            id: statuses.value.length + 1,
            text: newMessage
          })
        }

      watch(statusMessage, (newValue: string, oldValue: string) => {
        addStatus(statusMessage.value);
      })

      onMounted(() => {
          window.addEventListener("scroll", function (e) {
                let vertical_position = 0;
                vertical_position = pageYOffset;

                if(document.getElementById("slide")){
                  document.getElementById('slide').style.bottom = -(vertical_position) + 'px';
                }
          });
      })

    return {
      store,
      statuses,
      addStatus
    };
  },
  methods: {
        clearAllNotifications() {
          this.statuses = []
        },

        closeStatus(elm: any) {
          const index = this.statuses.map((status) => status.id).indexOf(elm.id);
          this.statuses.splice(index, 1);
        }
      }
  })
</script>

and here's the slide modal style:

    .slide-modal {
        max-height: 200px;
        width: 500px;
        background-color: #f2f2f2;
        color: #505050;
        padding: 8px;
        display: flex;
        flex-direction: column;
        gap: 8px;
        overflow-x: hidden;
        position: absolute;
        bottom: 0;
    }
like image 804
user581733 Avatar asked Oct 15 '25 14:10

user581733


1 Answers

The docs give a pretty simple example

<template>
  <div ref="root">This is a root element</div>
</template>

<script>
  import { ref, onMounted } from 'vue'

  export default {
    setup() {
      const root = ref(null)

      onMounted(() => {
        // the DOM element will be assigned to the ref after initial render
        console.log(root.value) // <div>This is a root element</div>
      })

      return {
        root
      }
    }
  }
</script>
  • use ref() when creating
  • pass to template in return function
  • use ref="..." in template
  • and in onMounted, access via ref.value

so for your code it would be...

<template>
  <div>
    <transition name="toast">
      <div ref="slideRef" class="slide-modal" v-if="statuses.length">
        <div class="clear-notifications" @click='clearAllNotifications()'>Clear all notifications</div>
        <div v-for="status in statuses" :key="status.id" class="status-div">
          <div>{{ status.text }}</div>
          <div @click="closeStatus(status)"><span class="-x10-cross"></span></div>
        </div>
      </div>
    </transition>
  </div>
</template>

<script lang="ts">
  import { defineComponent, ref, computed, watch, onMounted } from "vue";
  import { useStore } from "../model/DataStore";
  export default defineComponent({ 
    setup() {
    const store = useStore();

    const statuses = ref([]);
    const slideRef = ref();

    const statusMessage = computed(() => store.state.statusMessage);
    function  addStatus(newMessage) {
          statuses.value.push({
            id: statuses.value.length + 1,
            text: newMessage
          })
        }

      watch(statusMessage, (newValue: string, oldValue: string) => {
        addStatus(statusMessage.value);
      })

      onMounted(() => {
          window.addEventListener("scroll", function (e) {
                let vertical_position = 0;
                vertical_position = pageYOffset;

                if(slideRef.value){
                  slideRef.value.style.bottom = -(vertical_position) + 'px';
                }
          });
      })

    return {
      store,
      statuses,
      addStatus,
      slideRef 
    };
  },
  })
</script>
like image 139
Daniel Avatar answered Oct 18 '25 04:10

Daniel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!