Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to close v-select on click outside v-app?

I have an vue app that user vuetify. The app is used inside existing cms. When a dropdown select is opened a click outside the app does not close the dropdown. If the click is inside the app region, the dropdown closes.

Any idea how can I trigger close for the opened dropdown on click outside the app ?

new Vue({
  el: '#cartbutton',
  data() {
    return {
      items: [{text:'a'}, {text:'b'}]
    }
  }
})
.existing-cms {
  padding: 40px 50px;
}

#app {
  background-color: rgba(0,0,0,0.2);
  padding: 10px;
  height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vuetify/dist/vuetify.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Material+Icons" rel=stylesheet>

<div class="existing-cms">
  <p>Click on the select dropdown and leave it open.</p>
  <p>
    Click on this white region outside the app should somehow close
    opened select in the app.
  </p>
  
  <div id="cartbutton">
    <v-app>
      <span>Clicking here insde the app closed the opened select</span>
      <br><br>
      <v-select label="Click me and leave it opened. Then click in the white region." :items="items"></v-select>
    </v-app>
  </div>
  
</div>

Here is a codepen link https://codepen.io/darkopetreski/pen/OGMvop

EDIT:

It seems that this is reported as a bug here https://github.com/vuetifyjs/vuetify/issues/3144 and the suggestion is to use data-app="true" at the root element, but this approach is not good, since it will mess up stuff (at least was not working well for me).

like image 387
darpet Avatar asked May 08 '19 18:05

darpet


1 Answers

This is a rather hacky solution but it seems to work. There are two changes:

1) Add a window click listener that calls the blur method on the v-select. This hides the control. To facilitate this I added a ref to the v-select component.

2) To prevent this firing when they click inside the app or on the v-select, I added a stop propagation @click.stop onto the container.

https://codepen.io/anon/pen/BeoOMz

new Vue({
  el: '#cartbutton',
  data() {
    return {
      items: [{text:'a'}, {text:'b'}]
    }
  },
  mounted() {
    window.addEventListener("click",() => {
       this.$refs.select.blur();
    });    
  }
})
.existing-cms {
  padding: 40px 50px;
}

#app {
  background-color: rgba(0,0,0,0.2);
  padding: 10px;
  height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link href="https://unpkg.com/vuetify/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://unpkg.com/vuetify/dist/vuetify.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Material+Icons" rel=stylesheet>

<div class="existing-cms">
  <p>Click on the select dropdown and leave it open.</p>
  <p>
    Click on this white region outside the app should somehow close
    opened select in the app.
  </p>
  
  <div id="cartbutton" @click.stop>
    <v-app>
      <span>Clicking here insde the app closed the opened select</span>
      <br><br>
      <v-select ref="select" label="Click me and leave it opened. Then click in the white region." :items="items"></v-select>
    </v-app>
  </div>
  
</div>
like image 80
jcbdrn Avatar answered Sep 28 '22 01:09

jcbdrn