Categories
JavaScript Vue

Add a Time Picker to a Vue App with vue-timeselector

To make adding a time picker easier, we can use the vue-timeselector package.

First, we install it by running:

npm i vue-timeselector

Then we can use it by registering the component and putting it in the template:

<template>
  <div id="app">
    <timeselector v-model="time"></timeselector>
    <p>{{time}}</p>
  </div>
</template>

<script>
import Timeselector from "vue-timeselector";

export default {
  components: {
    Timeselector
  },
  data() {
    return {
      time: undefined
    };
  }
};
</script>

v-model binds the time property to the timeselector‘s value.

We can also use the placeholder and required props like a regular input component:

<template>
  <div id="app">
    <timeselector v-model="time" placeholder="Select a time" required></timeselector>
    <p>{{time}}</p>
  </div>
</template>

<script>
import Timeselector from "vue-timeselector";

export default {
  components: {
    Timeselector
  },
  data() {
    return {
      time: undefined
    };
  }
};
</script>

We can also add the disabled prop to disable interactivity:

<template>
  <div id="app">
    <timeselector v-model="time" disabled></timeselector>
    <p>{{time}}</p>
  </div>
</template>

<script>
import Timeselector from "vue-timeselector";

export default {
  components: {
    Timeselector
  },
  data() {
    return {
      time: undefined
    };
  }
};
</script>

The date format can be customized with the returnFormat prop:

<template>
  <div id="app">
    <timeselector v-model="time" returnFormat="HH" @formatedTime="formatTime"></timeselector>
    <p>{{formattedTime}}</p>
  </div>
</template>

<script>
import Timeselector from "vue-timeselector";

export default {
  components: {
    Timeselector
  },
  data() {
    return {
      time: undefined,
      formattedTime: undefined
    };
  },
  methods: {
    formatTime(time) {
      this.formattedTime = time;
    }
  }
};
</script>

We pass in the formatTime method which has the formatted time set as the value of the time parameter.

Then we set that value to this.formattedTime and display it.

returnFormat sets the format of the formatted time.

The interval of the hours and minutes can be changed with the interval prop:

<template>
  <div id="app">
    <timeselector v-model="time" displaySeconds :interval="{h:2, m:1, s:10}"></timeselector>
    <p>{{formattedTime}}</p>
  </div>
</template>

<script>
import Timeselector from "vue-timeselector";

export default {
  components: {
    Timeselector
  },
  data() {
    return {
      time: undefined
    };
  }
};
</script>

We set the interval prop to an object, h is for hour the hour interval, m for minute, and s for seconds.

Now we see that the hour picker only displays the even hours.

We can also disable some choices from the time picker with the disabled prop:

<template>
  <div id="app">
    <timeselector v-model="time" displaySeconds :disable="{h:[1, 5], m:null, s:[10,20,25]}"></timeselector>
    <p>{{time}}</p>
  </div>
</template>

<script>
import Timeselector from "vue-timeselector";

export default {
  components: {
    Timeselector
  },
  data() {
    return {
      time: undefined
    };
  }
};
</script>

We have the disable prop with an object to disable hour 1 and 2

vue-timeselector also provides slots to let us change the labels display.

There’s the hours, minutes, seconds, ampm and clear-ico slots to let us change the text of those labels.

For example, we can write:

<template>
  <div id="app">
    <timeselector v-model="time">
      <template slot="hours">
        <span>Hours</span>
      </template>
    </timeselector>
    <p>{{time}}</p>
  </div>
</template>

<script>
import Timeselector from "vue-timeselector";

export default {
  components: {
    Timeselector
  },
  data() {
    return {
      time: undefined
    };
  }
};
</script>

to set the hours heading to Hours.

vue-timeselector is an easy to use package to let us add a time picker to our Vue app.

It supports various formatting and customization options.

Categories
JavaScript Vue

Lazy Load Images in a Vue App with v-lazy-image

We can lazy load images in a Vue app with the v-lazy-image library.

Lazy loading images makes the image only load when it’s showing on the screen.

To install it, we can run:

npm i v-lazy-image

Once that’s done, we can register the plugin by writing:

import Vue from "vue";
import App from "./App.vue";
import { VLazyImagePlugin } from "v-lazy-image";

Vue.use(VLazyImagePlugin);
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

Then we can use the VLazyImage component by writing:

<template>
  <div id="app">
    <v-lazy-image src="http://placekitten.com/200/200"/>
  </div>
</template>

<script>
import VLazyImage from "v-lazy-image";

export default {
  name: "App",
  components: {
    VLazyImage
  },
  methods: {}
};
</script>

src has the URL of the image.

We can also add a placeholder image by using the src-placeholder prop:

<template>
  <div id="app">
    <v-lazy-image
      src="http://placekitten.com/200/200"
      src-placeholder="http://placekitten.com/400/400"
    />
  </div>
</template>

<script>
import VLazyImage from "v-lazy-image";

export default {
  name: "App",
  components: {
    VLazyImage
  }
};
</script>

We can also add some styles to the component by adding styles to the v-lazy-image and v-lazy-image-loaded classes. The 2nd one is applied when the image is loaded.

For instance, we can write:

<template>
  <div id="app">
    <v-lazy-image
      src="http://placekitten.com/200/200"
      src-placeholder="http://placekitten.com/400/400"
    />
  </div>
</template>

<script>
import VLazyImage from "v-lazy-image";

export default {
  name: "App",
  components: {
    VLazyImage
  }
};
</script>

<style scoped>
.v-lazy-image {
  filter: blur(20px);
  transition: filter 0.7s;
}
.v-lazy-image-loaded {
  filter: blur(0);
}
</style> 

to add some blur effect when it’s being loaded.

We can load different images according to the screen size.

To do that, we use the srcset prop.

For instance, we can write:

<template>
  <div id="app">
    <v-lazy-image
      srcset="https://cdn.pixabay.com/photo/2020/02/25/19/16/stawberry-4879794_960_720.jpg 1x, https://cdn.pixabay.com/photo/2020/02/06/08/51/water-4823443__340.jpg 2x"
      src="http://placekitten.com/400/400"
    />
  </div>
</template>

<script>
import VLazyImage from "v-lazy-image";

export default {
  name: "App",
  components: {
    VLazyImage
  }
};
</script>

We need both the src and srcset attributes. src is for the fallback image.

v-lazy-image is used for letting us lazy load images, which means that it only loads when it’s in the viewport.

It supports responsiveness and styling.

Categories
JavaScript Vue

Adding Keyboard Shortcut Handling to a Vue App with vue-shortkey

We can use the vue-shortkey package to add shortcut key handling to our Vue app.

To use it, we first install it by running:

npm i vue-shortkey

Then we can use it by writing:

<template>
  <div id="app">
    <button v-shortkey="['ctrl', 'alt', 'o']" @shortkey="theAction()">Open</button>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    theAction() {
      alert("hello");
    }
  }
};
</script>

We have a button that responds to the keyboard shortcut Ctrl+Alt+O.

When we press it, theAction will be called because we passed it into the shortkey event handler.

Then we should see the ‘hello’ alert displayed when we pressed the key combination.

We can also handle multiple key combinations with one handler.

For instance, we can write:

<template>
  <div id="app">
    <button v-shortkey="{up: ['arrowup'], down: ['arrowdown']}" @shortkey="theAction">arrow</button>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    theAction(event) {
      switch (event.srcKey) {
        case "up":
          alert("up");
          break;
        case "down":
          alert("down");
          break;
        default:
          break;
      }
    }
  }
};
</script>

We have the v-shortkey directive with an object with the up and down keys.

We have an array with the values as the values of the objecy.

Then in theAction, we take an event parameter which has the key we pressed.

We then have the switch statement and then we have alerts displayed according to the key pressed.

It can also be used on a component. However, we have to add the native modifier to catch the event.

For instance, we can write:

<template>
  <div id="app">
    <HelloWorld v-shortkey="['ctrl', 'alt', 'o']" @shortkey.native="theAction"/>
  </div>
</template>

<script>
import HelloWorld from "@/components/HelloWorld";

export default {
  name: "App",
  components: {
    HelloWorld
  },
  methods: {
    theAction() {
      alert("hello");
    }
  }
};
</script>

We added the v-shortkey directive to the HelloWorld component, and we used the native modifier on @shortkey so that the handler is run.

The full list of keys are at https://www.npmjs.com/package/vue-shortkey

vue-shortkey is a simple package that lets us add shortcut key handling capability to a Vue app that’s easier to use than the Vue way.

Categories
JavaScript Vue

Using the Intersection Observer API in a Vue App with Vue Intersect

We can use the Vue Intersect package to use the intersection observer API in our app.

To install it, we run:

npm install vue-intersect --save

or:

yarn add vue-intersect

Then we can use it by using the intersect component that comes with the package.

For instance, we can write:

<template>
  <div id="app">
    <div style="height: 300px; overflow-y: scroll">
      <intersect @enter="onEnter" @leave="onLeave" v-for="a of arr" :key="a">
        <div :id="a">{{ a }}</div>
      </intersect>
    </div>
    <div>in screen: {{inScreen.join(', ')}}</div>
  </div>
</template>

<script>
import Intersect from "vue-intersect";

export default {
  name: "App",
  components: { Intersect },
  data() {
    return {
      arr: Array(100)
        .fill()
        .map((_, i) => i),
      inScreen: []
    };
  },
  methods: {
    onEnter(e) {
      this.inScreen.push(e[0].target.id);
      this.inScreen = [...new Set(this.inScreen)];
    },
    onLeave(e) {
      const index = this.inScreen.indexOf(e[0].target.id);
      this.inScreen.splice(index, 1);
      this.inScreen = [...new Set(this.inScreen)];
    }
  }
};
</script>

We have the intersect component, which we pass the enter and leave handlers into.

We set them to onEnter and onLeave respectively.

In the methods, we have the e object, which is the event objects.

We assigned the ID to each item that we rendered with v-for, so we can get the id property of those elements that enter the screen in onEnter and the ones the left the screen in onLeave.

We add the ones that are on the screen to the inScreen array.

Likewise, we do the same with the ones that left the screen in onLeave.

We remove the duplicates by converting them to a set and then converting back to an array.

The div is made scrollable by setting its height to 300px and setting the overflow-y property to scroll.

Then when the elements enter or leave the div’s displayed area, those callbacks will be called.

We displayed the IDs of the items that are displayed in the bottom div.

vue-intersect lets us use the intersection observer API to detect if something is in the viewport easily.

Categories
JavaScript Vue

Create Styled Vue Components Easily with vue-styled-components

To created component with built-in styles with a few lines of code, we can use the vue-styled-components to create them.

Getting Started

First, we install the package by running:

npm i vue-styled-components

Then we can create some basic components by writing:

import styled from "vue-styled-components";

export const StyledTitle = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

export const StyledHeader = styled.header`
  padding: 4em;
  background: yellow;
`;

We import the package then use the template tags that came with the code to create new styled elements.

We change the font size, text alignment, and other things with the tags.

The h1 tag makes an h1 element.

header makes a styled header element.

Then we can use it by registering the component and use it:

<template>
  <div id="app">
    <styled-header>
      <b>header</b>
    </styled-header>
    <styled-title>hello</styled-title>
  </div>
</template>

<script>
import { StyledTitle, StyledHeader } from "./components";

export default {
  name: "App",
  components: {
    "styled-title": StyledTitle,
    "styled-header": StyledHeader
  }
};
</script>

We just register them in components and reference it in our templates.

The styles in the string are applied automatically.

Props

Like any other component, we can pass props to them.

We can create an element by writing:

import styled from "vue-styled-components";

export const StyledInput = styled.input`
  font-size: 1.25em;
  padding: 0.5em;
  margin: 0.5em;
  color: palevioletred;

  &:hover {
    box-shadow: inset 1px 1px 2px red;
  }
`;

Then we can write:

<template>
  <div id="app">
    <styled-input v-model="val" placeholder="val"/>
    <p>{{val}}</p>
  </div>
</template>

<script>
import { StyledInput } from "./components";

export default {
  name: "App",
  data() {
    return {
      val: ""
    };
  },
  components: {
    "styled-input": StyledInput
  }
};
</script>

Whatever we entered is displayed below it.

This is because it takes the value prop and emits the input event like any other component.

The styles we specified are also applied.

The placeholder prop also works and the placeholder is applied.

Adapting Based on Props

We can change styling based on props that we passed in.

For instance, we can write:

import styled from "vue-styled-components";

const btnProps = { primary: Boolean };

export const StyledButton = styled("button", btnProps)`
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
  background: ${props => (props.primary ? "green" : "white")};
  color: ${props => (props.primary ? "white" : "red")};
`;

to let our component takes props.

We specify the btnProps object to let our StyledButton takes props.

btnProps specifies the props that our component takes. We specified that our component takes the primary prop.

Then we can use it by writing:

<template>
  <div id="app">
    <styled-button primary>button</styled-button>
  </div>
</template>

<script>
import { StyledButton } from "./components";

export default {
  name: "App",
  data() {
    return {
      val: ""
    };
  },
  components: {
    "styled-button": StyledButton
  }
};
</script>

We set the primary prop to true, so we get a green background and white text.

Conclusion

We can create styled-components with vue-styled-components.

The package lets us create elements with styles applied to them so we can use them as Vue components.