Home » vue » How do I add an onclick event to a Vue element by ref?

How do I add an onclick event to a Vue element by ref?

Posted by: admin November 26, 2021 Leave a comment

Questions:

I’m using Vue Cesium, and having a bit of trouble getting the desired behavior from the various Vue elements I’m adding to my map. Specifically, I want to get the element’s id (created programmatically with v-for) and dispatch an action with it. I can add refs to the element. Is there a way I can programmatically add an onclick action to an element by ref? If there were a more organic way that I can use the Cesium library for this, it would be even better.

Here’s the relevant element:

div class="viewer">
            <vc-viewer :terrainExaggeration="100" @ready="ready" :camera="camera">
                <div v-if="billboards.length > 0" v-for="billboard in billboards">
                    <vc-entity :ref="billboard.id" @click="selectCommunity(billboard.id)" :position="billboard.position" :billboard="billboard" :description="billboard.description" :id="billboard.id.toString()"> </vc-entity>
                </div>
                <vc-layer-imagery :alpha="alpha" :brightness="brightness" :contrast="contrast">
                    <vc-provider-imagery-bingmaps :url="url" :bmKey="bmKey" :mapStyle="mapStyle">
                    </vc-provider-imagery-bingmaps>
                </vc-layer-imagery>
            </vc-viewer>
        </div>
Answers:

The Cesium equivalent to click appears to be the “pick” event, which, frustratingly, doesn’t appear to be exposed by the VC API. It looks like you might be able to use the LEFT_CLICK event on the viewer and use it to find the clicked entity. This SO question shows an example of locating entities from events on the viewer.

Taking a stab at a sample impl by combining the two ref’s above with your sample, something like this might work:

<template>
    <vc-viewer :terrainExaggeration="100"
               @ready="ready"
               :camera="camera"
               ref="viewer"
               @LEFT_CLICK="onClick"
    >
        <vc-entity v-for="billboard in billboards"
                   :ref="billboard.id"
                   :position="billboard.position"
                   :billboard="billboard"
                   :description="billboard.description"
                   :id="billboard.id.toString()"
        />
        <vc-layer-imagery :alpha="alpha" :brightness="brightness" :contrast="contrast">
            <vc-provider-imagery-bingmaps :url="url" :bmKey="bmKey" :mapStyle="mapStyle">
            </vc-provider-imagery-bingmaps>
        </vc-layer-imagery>
    </vc-viewer>
</template>

<script>
export default {
  // ...ext'g
  methods: {
    // ...ext'g
    onClick (click) {
      const viewer = this.$refs.viewer;
      const pickedObject = viewer.scene.pick(click.position);
      if (Cesium.defined(pickedObject)) {
        const entityId = pickedObject.id._id;
        this.selectCommunity(entityId);
      }
    }
  }
}
</script>


(completely unrelated note: it’s not necessary to wrap vc-entity in a div and it might cause unwanted side effects.)

###

The answer, thanks to Zouyaoji, appears here: https://github.com/zouyaoji/vue-cesium/issues/41#issuecomment-563029965.

In short, the vc-viewer element has two events that could be used for this: LEFT_CLICK and selectedEntityChanged.