Mushr00m
Mushr00m

Reputation: 2356

VueJS and JQuery changing classes

I have a some custom JQuery code that listen to events and add some classes to form elements (focus, blur, odd/even, etc). Nothing big but I would like not to re-writte all this logic in VueJS since all the website use only JQuery and 1 page uses VueJS for a complex form.

I wrote a Directive to launch the JQuery code on new VueJS elements and it's working. But some VueJS code (vee-validate directive plugin in my case but it can be any VueJS code) changes the classes using v-bind:class. So it erase the classes sets by JQuery, it doesn't add its classes it replace them... Is there any way to play nicely with classes from VueJS and JQuery/Javascript ? Make JQuery aware of existing classes or something.

Thanks

Upvotes: 1

Views: 1388

Answers (1)

vbranden
vbranden

Reputation: 5986

You can accomplish this with a MutationObserver https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

The following example will set up a vuejs app that when clicked on changes the class from on to off and back modifying the class list via vue. It will then set up a mutation observer to look for changes to the class attribute and run some more jquery to check if a makeBold class is in the class list and if not add it.

this demonstrates that vue is controlling the elements class list and the observer is reacting to changes by executing some jquery

additionally i have added a checkbox to disable the oberserver reaction to show that vue is removing the makeBold class

const app = new Vue({
  el: '#app',
  data() {
    return {
      on: true
    }
  }
})
const node = document.getElementById('app')
// add bold class with jQuery
$('#app').addClass('makeBold')

const observer = new MutationObserver(mutations => {
  if ($('#cbx').prop('checked')) return
  const changes = mutations
    .filter(({ attributeName }) => attributeName === 'class');
  if (changes.length && !$('#app').hasClass('makeBold')) {
    $('#app').addClass('makeBold')
  }
})

observer.observe(node, { attributes: true })
.on {
  background-color: orange;
}

.off {
  background-color: white;
}
.makeBold {
  font-weight: 600;
}
.appBody {
  height: 100px;
  border: 1px solid #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="app" class="appBody" :class="{ 'on': on, 'off': !on }" @click="on=!on">
  Click Me
</div>
<input type="checkbox" id="cbx"> Disable Observer reaction

Upvotes: 2

Related Questions