9

I'm trying to create simple app with Vuejs that will check length of title tag (px).

Inside mounted I set the default value for title and run check length of default title tag but it return 0. When I change value of input, it work fine.

Here is my code. Link: https://codepen.io/mrtienhp97/pen/LeOzGa

HTML:

<div id="app">
   <input v-model="title" @input="titleCheck()">

  <div id="title-preview">{{title}}</div>

  <div class="message">{{message}}</div>
</div>

CSS:

#title-preview {
  display: inline-block;
}

JS:

new Vue({
  el: '#app',
  data: {
    title: '',
    message: ''
  },
  mounted: function() {
    this.$nextTick(function () {
      this.title = "Default Title";
      var title_width = document.getElementById("title-preview").offsetWidth;
      this.message = title_width + 'px';
    });
  },
  methods: {
    titleCheck: function() {
      var title_width = document.getElementById("title-preview").offsetWidth;
      this.message = title_width + 'px';
    }
  }
})

Can anyone help me correct it?

1
  • 1
    The reason is that the whole mounted() is happening before the rendering of the page. You should delay it somehow. I'm still trying to figure out a good answer though. Commented Jan 6, 2018 at 16:59

1 Answer 1

5

You had the right idea in the mounted event to use the $nextTick to make sure the view was updated before getting the width, but you want to do that every time by making it part of titleCheck. Here's what you can change to get it working:

  1. Add a ref attribute to title-preview so you don't need to use document.getElementById (nothing wrong with it, but I prefer to let Vue do that for me)

<div id="title-preview" ref="titleRef">{{title}}</div>

  1. Change titleCheck to use $nextTick as well as the $refs to get title-preview:
titleCheck: function() {
  this.$nextTick(function () {
    var title_width = this.$refs.titleRef.offsetWidth;
    this.message = title_width + 'px';
  });
}
  1. You can simplify your mounted event to set the title and then call your titleCheck method:
mounted: function() {
  this.title = "Default Title";
  this.titleCheck();
}

This should get you what you're looking for.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi Patrick, it work if i add static data to title. But when i try to set dynamic title by getting data with axios( in mounted, i add these code axios.get('request url')... and this.title = response.data ), message return 0. I know my "axios" code is right because i can see value in input. Thank you
Had to tell without seeing your axios callback, but I suspect the this you're using to set this.title is not the Vue instance. Trying saving the instance (var vm = this;) in a variable before calling axios and then in the axios callback, use vm.title = response.data.
@PatrickSteele I've the same issue. Saving the instance (var vm = this; ) works for me. Can you please explain this behavior?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.