Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Learning Vue.js 2

You're reading from   Learning Vue.js 2 Learn how to build amazing reactive web applications easily with Vue.js

Arrow left icon
Product type Paperback
Published in Dec 2016
Publisher Packt
ISBN-13 9781786469946
Length 334 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Olga Filipova Olga Filipova
Author Profile Icon Olga Filipova
Olga Filipova
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. Going Shopping with Vue.js FREE CHAPTER 2. Fundamentals – Installing and Using 3. Components – Understanding and Using 4. Reactivity – Binding Data to Your Application 5. Vuex – Managing State in Your Application 6. Plugins – Building Your House with Your Own Bricks 7. Testing – Time to Test What We Have Done So Far! 8. Deploying – Time to Go Live! 9. What Is Next? A. Solutions to Exercises

Let's manage time!

At this point of time, I already know that you are so, so, so enthusiastic with this book that you want to read it to the end without stopping. But this is not right. We should manage our time and give us some time to work and some time to rest. Let's create a small application that implements a Pomodoro technique timer so that it can help us in our working time management.

Note

The Pomodoro technique is a time management technique named after the kitchen tomato timer (in fact, Pomodoro means tomato in Italian). This technique consists of breaking down the working time into small intervals separated by short breaks. Read more about the Pomodoro technique on the official site: http://pomodorotechnique.com/ .

Thus, our goal is very simple. We just have to create a very simple time counter that will decrement untill the end of the working interval and then restart and decrement till the end of the resting time and so on.

Let's do that!

We will introduce two Vue data variables, minute and second, which will be displayed on our page. The main method on each second will decrement second; it will decrement minute when second becomes 0; and when both minute and second variables come to 0, the application should toggle between working and resting interval:

Our JavaScript code will look like the following:

const POMODORO_STATES = { 
  WORK: 'work', 
  REST: 'rest' 
}; 
const WORKING_TIME_LENGTH_IN_MINUTES = 25; 
const RESTING_TIME_LENGTH_IN_MINUTES = 5; 
 
new Vue({ 
  el: '#app', 
  data: { 
    minute: WORKING_TIME_LENGTH_IN_MINUTES, 
    second: 0, 
    pomodoroState: POMODORO_STATES.WORK, 
    timestamp: 0 
  }, 
  methods: { 
    start: function () { 
      this._tick(); 
      this.interval = setInterval(this._tick, 1000); 
    }, 
    _tick: function () { 
      //if second is not 0, just decrement second 
      if (this.second !== 0) { 
        this.second--; 
        return; 
      } 
      //if second is 0 and minute is not 0,        
      //decrement minute and set second to 59 
      if (this.minute !== 0) { 
        this.minute--; 
        this.second = 59; 
        return; 
      } 
      //if second is 0 and minute is 0,        
      //toggle working/resting intervals 
      this.pomodoroState = this.pomodoroState ===        
      POMODORO_STATES.WORK ? POMODORO_STATES.REST :        
      POMODORO_STATES.WORK; 
      if (this.pomodoroState === POMODORO_STATES.WORK) { 
        this.minute = WORKING_TIME_LENGTH_IN_MINUTES; 
      } else { 
        this.minute = RESTING_TIME_LENGTH_IN_MINUTES; 
      } 
    } 
  } 
}); 

In our HTML code, let's create two placeholders for minute and second, and a start button for our Pomodoro timer:

<div id="app" class="container"> 
  <h2> 
    <span>Pomodoro</span> 
    <button  @click="start()"> 
      <i class="glyphicon glyphicon-play"></i> 
    </button> 
  </h2> 
  <div class="well"> 
    <div class="pomodoro-timer"> 
      <span>{{ minute }}</span>:<span>{{ second }}</span> 
    </div> 
  </div> 
</div> 

Again, we are using Bootstrap for the styling, so our Pomodoro timer looks like the following:

Let's manage time!

Countdown timer built with Vue.js

Our Pomodoro is nice, but it has some problems:

  • First of all, we don't know which state is being toggled. We don't know if we should work or rest. Let's introduce a title that will change each time the Pomodoro state is changed.
  • Another problem is inconsistent display of minutes and seconds numbers. For example, for 24 minutes and 5 seconds, we would like to see 24:05 and not 24:5. Let's fix it introducing computed values in our application data and displaying them instead of normal values.
  • Yet another problem is that our start button can be clicked over and over again, which creates a timer each time it's clicked. Try to click it several times and see how crazy your timer goes. Let's fix it by introducing start, pause, and stop buttons, apply application states to them, and disable buttons to the state accordingly.

Toggle the title by using computed properties

Let's start by fixing the first problem by creating computed property title and using it in our markup.

Note

Computed properties are the properties inside the data object that allow us to avoid blowing up the template with some extra logic. You can find more information about computed properties on the official documentation site: http://vuejs.org/guide/computed.html .

Add the computed section in the Vue options object and add the property title there:

data: { 
  //... 
}, 
computed: { 
  title: function () { 
    return this.pomodoroState === POMODORO_STATES.WORK ? 'Work!' :      
    'Rest!' 
  } 
}, 
methods: { 
//... 

And now just use the following property as it was a normal Vue data property in your markup:

  <h2> 
    <span>Pomodoro</span> 
    <!--!> 
  </h2> 
  <h3>{{ title }}</h3> 
  <div class="well"> 

And voilà! Now we have a title that changes each time the Pomodoro state is being toggled:

Toggle the title by using computed properties

Automatic change of the title based on the state of the timer

Nice, isn't it?

Left-pad time values using computed properties

Now let's apply the same logic for left padding our minute and second numbers. Let's add two computed properties, min and sec, in our computed section in the data options and apply the simple algorithm to pad the numbers with 0 on the left. Of course, we could use a famous left-pad project ( https://github.com/stevemao/left-pad ), but to keep things simple and not to break the whole Internet ( http://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/ ), let's apply a simple logic of our own:

computed: { 
  title: function () { 
    return this.pomodoroState === POMODORO_STATES.WORK ? 'Work!' :      
    'Rest!' 
  }, 
  min: function () { 
    if (this.minute < 10) { 
      return '0' + this.minute; 
    } 
 
    return this.minute; 
  }, 
  sec: function () { 
    if (this.second < 10) { 
      return '0' + this.second; 
    } 
 
    return this.second; 
  } 
} 

And let's use these properties instead of minute and second in our HTML code:

   <div class="pomodoro-timer"> 
    <span>{{ min }}</span>:<span>{{ sec }}</span> 
   </div> 

Refresh a page and check how beautiful our numbers are now:

Left-pad time values using computed properties

Left padding using computed properties in Vue.js

Keep state with start, pause, and stop buttons

So, to fix the third problem, let's introduce three application states, started, paused, and stopped, and let's have three methods that would allow us to permute over these states. We already have the method that starts the application, so we just add the logic there to change the state to started. We also add two additional methods, pause and stop, which would pause the timer and change to the corresponding application state:

const POMODORO_STATES = { 
  WORK: 'work', 
  REST: 'rest' 
}; 
const STATES = { 
  STARTED: 'started', 
  STOPPED: 'stopped', 
  PAUSED: 'paused' 
}; 
//<...> 
new Vue({ 
  el: '#app', 
  data: { 
    state: STATES.STOPPED, 
    //<...> 
  }, 
  //<...> 
  methods: { 
    start: function () { 
      this.state = STATES.STARTED; 
      this._tick(); 
      this.interval = setInterval(this._tick, 1000); 
    }, 
    pause: function () { 
      this.state = STATES.PAUSED; 
      clearInterval(this.interval); 
    }, 
    stop: function () { 
      this.state = STATES.STOPPED; 
      clearInterval(this.interval);  
      this.pomodoroState = POMODORO_STATES.WORK; 
      this.minute = WORKING_TIME_LENGTH_IN_MINUTES; 
      this.second = 0; 
    }, 
    //<...> 
  } 
}); 

And, let's add two buttons to our HTML code and add the click listeners that call the corresponding methods:

    <button :disabled="state==='started'"
@click="start()"> 
      <i class="glyphicon glyphicon-play"></i> 
    </button> 
    <button :disabled="state!=='started'"       
      @click="pause()"> 
      <i class="glyphicon glyphicon-pause"></i> 
    </button> 
    <button :disabled="state!=='started' && state !== 'paused'"      
       @click="stop()"> 
      <i class="glyphicon glyphicon-stop"></i> 
    </button> 

Now our application looks nice and allows us to start, pause, and stop the timer:

Keep state with start, pause, and stop buttons

Toggling start, stop, and pause buttons according to the application state

Check what the whole code looks like in JSFiddle at  https://jsfiddle.net/chudaol/b6vmtzq1/1/.

After so much work and so many of new terms and knowledge, you certainly deserve a kitten! I also love kittens, so here you have a random kitten from the awesome site http://thecatapi.com/ :

Keep state with start, pause, and stop buttons

You have been reading a chapter from
Learning Vue.js 2
Published in: Dec 2016
Publisher: Packt
ISBN-13: 9781786469946
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime