Adrián S. Basave
Adrián S. Basave

Reputation: 33

In vuejs, how do I reference data from function that is done within a method?

I need to pass a value to a style property inside data, but, because of how vuejs and how JS scopes work, it won't let me access through this.data.property:

Vue.component ('loader-component', {
  template: '#loader-template',

  mounted: function() {
    this.animationTest();
  },

  data: function() {
    return {
      svg: true,
      timer: 0,
      // styles
      position: {
        marginLeft: '',
        marginTop: '',
        float: 'left'
      }
    };
  },

  methods: {
    animation: function() {
      let timer = 0,
          itemWidth = 60,
          domWidth = document.getElementById('awesome-body').clientWidth,
          domHeight = document.getElementById('awesome-body').clientHeight,
          marginL = -2 * itemWidth,
          marginT = Math.floor((Math.random() * domHeight) + 1);
          this.position.marginTop = marginT;
      setInterval(function() {
        marginL = marginL + timer * 5;
        timer++;
        // console.log(marginL);
        this.position.marginLeft = marginL;
      }, 1000); // time interval in milliseconds
    }
  } // methods finishes

});

This will trigger the next error:

Cannot set property 'marginLeft' of undefined.

What's the syntax to go directly from the setInterval function to data.marginTop?

Thanks!

Upvotes: 0

Views: 2619

Answers (2)

Existe Deja
Existe Deja

Reputation: 1379

I think you should try another approach. The problem is that you are referring to an element that isn't rendered yet.

There is several ways to accomplish what you want to do.

1/ style binding

With this approach you'll be able to bind data to style, and when your data is updated it automatically update your template.

<template>
  <div :style="{ 'margin-left': whateverFunction() }">
  </div>
</template>

<script>
  ...
  methods: {
    whateverFunction () {
      return this.some_attribute + 'px'
    }
  }
  ...
</script>

Instead of a function, this also could be a computed property, or an attribute too.

2/ Transition built-in system

You seem want to achieve a transition on an element, so the simple way to do that is to use the built-in system. And if you want to have more control in your transition, there is javascript hooks to help you manipulate the data during the transition time.

3/ play with booleans and ref

If you really want to access to DOM element inside your code, you should use boolean to wait until your template is totally rendered enter link description here and use ref special attribute to easily get the desired element.

If you want specific help on a part of your code, give us a jsfiddle to test and debug it.

Upvotes: 0

Adam
Adam

Reputation: 3288

The this is referencing the setInterval function and not the component. Do this:

methods: {
    animation: function() {
      let component = this,
          timer = 0,
          itemWidth = 60,
          domWidth = document.getElementById('awesome-body').clientWidth,
          domHeight = document.getElementById('awesome-body').clientHeight,
          marginL = -2 * itemWidth,
          marginT = Math.floor((Math.random() * domHeight) + 1);

      component.position.marginTop = marginT;

      setInterval(function() {
        marginL = marginL + timer * 5;
        timer++;
        // console.log(marginL);
        component.position.marginLeft = marginL;
      }, 1000); // time interval in milliseconds
    }
}

Upvotes: 2

Related Questions