mimic
mimic

Reputation: 5224

Vue: How to bind property dynamically to a new DOM element

Say, I have a component with the following template:

<div id="root"></div>

Then somehow I call the code that appends a new element to it (using jQuery for now):

$('#root').append('<div id="a1" v-bind:styles="styles.a1"></div>')

where "styles.a1" is just an object from component's data:

data() {
   return {
      styles: { a1: {color: 'red'} }
   };
}

I suppose the newborn element's binding will not work because Vue doesn't know anything about this new element and its binding.

But maybe there is some way to implement the desired logic?

PS I know that Vue's nature is to manipulate with data, not DOM but here is the situation I have to deal with.

Upvotes: 1

Views: 3351

Answers (2)

NeonNatureEX
NeonNatureEX

Reputation: 497

You can bind a style without a value first,

data() {
   return {
      styles: { a1: '' }
   };
}

then you can add data into that from an event via normal JS. (JQuery isn't even necessary here).

methods: {
   quack() {
        this.styles.a1 = { color: red }
    }
}

Edit: I got it wrong. Seems Vue does not detect newly added elements after being mounted. So what you can do is mount the Vue instance after the appended elements are added or to re-render the whole instance with forceUpdate . (The latter will re-render the whole instance so I recommend breaking down into multiple Vue instances for the sake of performance)

ForceUpdate

Upvotes: 1

Victor
Victor

Reputation: 22198

If you're using Vue components you shouldn't be manipulating the DOM.

  • You should either use template logic for that.

       <template v-if="someCondition">
           <div id="a1" v-bind:styles="styles.a1"></div>
       </template>
    
  • Wrap non Vue code inside it's own Vue component.

    Vue.component('date-picker', {
      template: '<input/>',
      mounted: function() {
        $(this.$el).datepicker();
      },
      beforeDestroy: function() {
        $(this.$el).datepicker('hide').datepicker('destroy');
      }
    });
    

    https://vuejsdevelopers.com/2017/05/20/vue-js-safely-jquery-plugin/

  • Use a custom directive.

    Vue.directive('demo', {
        bind: function () {
            $(this.el).css({color:'#fff', backgroundColor:this.arg});
        },
        update: function (value) {
            $(this.el).html(
                'argument - ' + this.arg + '!<br>' +
                'key - ' + this.key + '<br>' +
                'value - ' + value);
        }
    });
    
    

Upvotes: 1

Related Questions