Tutorial: Giphy gif picker (Vue3)
Tags: webdev, javascript, beginners, giphy
Published: 2024-06-17 06:47:41

I hope you have a basic understanding of Vue3 and Tailwind CSS.

## Step 1: Setup Vue 3 Project
Ensure you have a basic Vue 3 project set up. If not, you can create one using Vue CLI:

```
vue create my-project
cd my-project
```

## Step 2: Install Giphy Packages
Install the required Giphy packages using npm or yarn:

```
# Using npm
npm install @giphy/js-fetch-api @giphy/js-components

# Or using yarn
yarn add @giphy/js-fetch-api @giphy/js-components
```

## Step 3: Create Home Page Component
Create a Home.vue component to serve as the main page for the GIF picker:

```
//Home.vue
<script setup>
import {ref} from 'vue'
import GifPicker from '@/components/giphy/GifPicker.vue';

let showGifPicker = ref(false);
let gifUrl = ref('');

const handleGifSelection = (gif) => {
    showGifPicker.value = false;
    gifUrl.value = gif;
}
</script>

<template>
    <div class="relative flex flex-col items-center justify-center w-full">

        <GifPicker v-if="showGifPicker"
            @handleGifSelect="handleGifSelection"
            class="absolute text-black bottom-14"/>
        <button @click="showGifPicker = !showGifPicker"
            class="bg-green-700 p-4 rounded-2xl text-white">Pick Gif</button>
        <img v-if="gifUrl"
            :src="gifUrl"
            class="w-40 h-auto rounded-2xl absolute top-20"/>
            
    </div>
</template>
```

## Step 4: Create the GifPicker Component
Create a GifPicker.vue component to handle GIF selection:

```
<script setup></script>
<template>
    <div class="flex flex-col items-center justify-center w-[280px] h-[350px] bg-white shadow-lg rounded-2xl border p-4">
        <div class="flex items-center justify-between w-full">
            <input
                type="text"
                v-model="searchTerm"
                @input="handleGifSearch"
                class="w-full text-xl p-2 border rounded-xl"
                placeholder="Search gif"/>
            <span @click="handleTrendingClick" class=" ml-2 text-xl p-2 bg-white border flex items-center justify-center rounded-xl hover:bg-gray-100 cursor-pointer">🔥</span>
        </div>

        <div class="flex flex-wrap items-center justify-center w-full h-full overflow-y-auto">
            <div class="mt-2" ref="gifs"/>
        </div>
    </div>
</template>
```

Let's work on the gif picker scripting

**Setup Imports and Initialization**
Import necessary modules and initialize required variables:

```
<script setup>
import {ref,onMounted} from 'vue'
import { renderGrid } from '@giphy/js-components'
import { GiphyFetch } from '@giphy/js-fetch-api'
import { debounce } from 'lodash';

const emit = defineEmits(['handleGifSelection'])

let gifs = ref(null),
    searchTerm = ref(''),
    grid = null;

const gf = new GiphyFetch('your Web SDK key') // update your giphy key

const fetchGifs = (offset) => {
    if (searchTerm.value) {
        return gf.search(searchTerm.value, { offset, limit: 25 })
    }
    return gf.trending({ offset, limit: 25 })
}
Create Grid Rendering Function
Define a function to render the GIF grid:

const makeGrid = (targetEl) => {
    const render = () => {
        return renderGrid(
            {
                width: 226,
                fetchGifs,
                columns: 2,
                gutter: 6,
                noLink: true,
                hideAttribution: true,
                onGifClick,
            },
            targetEl
        )
    }
    const remove = render()
    return {
        remove: () => {
            remove()
        },
    }
}
```

**Handle GIF Clicks**
Define a function to handle GIF clicks and emit the selected GIF URL:

```
const onGifClick = (gif, e) => {
    e.preventDefault();
    emit('handleGifSelection', gif.images.fixed_height.url);
}
Handle Grid Refresh and Fetch New GIFs
Define functions to refresh the grid and fetch new GIFs based on search or trending clicks:

const clearGridAndFetchGifs = () => {
    grid.remove();
    grid=makeGrid(gifs.value)
}

const handleGifSearch = debounce(() => {
    clearGridAndFetchGifs();
},500)

const handleTrendingClick = () => {
    searchTerm.value = '';
    clearGridAndFetchGifs();
}
```

**Initialize Grid on Component Mount**
Initialize the grid when the component is mounted:

```
onMounted(() => {
    grid = makeGrid(gifs.value)
})
```

**Final GifPicker Component**
Combine all the pieces into the final GifPicker component:

```
<script setup>
import {ref,onMounted} from 'vue'
import { renderGrid } from '@giphy/js-components'
import { GiphyFetch } from '@giphy/js-fetch-api'
import { debounce } from 'lodash';

const emit = defineEmits(['handleGifSelection'])

let gifs = ref(null),
    searchTerm = ref(''),
    grid = null;

const gf = new GiphyFetch('your Web SDK key') // update your giphy key

onMounted(() => {
    grid = makeGrid(gifs.value)
})

const fetchGifs = (offset) => {
    if (searchTerm.value) {
        return gf.search(searchTerm.value, { offset, limit: 25 })
    }
    return gf.trending({ offset, limit: 25 })
}

const makeGrid = (targetEl) => {
    const render = () => {
        return renderGrid(
            {
                width: 226,
                fetchGifs,
                columns: 2,
                gutter: 6,
                noLink: true,
                hideAttribution: true,
                onGifClick,
            },
            targetEl
        )
    }
    const remove = render()
    return {
        remove: () => {
            remove()
        },
    }
}

const onGifClick = (gif, e) => {
    e.preventDefault();
    emit('handleGifSelection', gif.images.fixed_height.url);
}

const handleGifSearch = debounce(() => {
    clearGridAndFetchGifs();
},500)

const handleTrendingClick = () => {
    searchTerm.value = '';
    clearGridAndFetchGifs();
}

const clearGridAndFetchGifs = () => {
    grid.remove();
    grid=makeGrid(gifs.value)
}

</script>

<template>
    <div class="flex flex-col items-center justify-center w-[280px] h-[350px] bg-white shadow-lg rounded-2xl border p-4">
        <div class="flex items-center justify-between w-full">
            <input
                type="text"
                v-model="searchTerm"
                @input="handleGifSearch"
                class="w-full text-xl p-2 border rounded-xl"
                placeholder="Search gif"/>
            <span @click="handleTrendingClick" class=" ml-2 text-xl p-2 bg-white border flex items-center justify-center rounded-xl hover:bg-gray-100 cursor-pointer">🔥</span>
        </div>

        <div class="flex flex-wrap items-center justify-center w-full h-full overflow-y-auto">
            <div class="mt-2" ref="gifs"/>
        </div>
    </div>
</template>
```
**Final gif picker result**

![Giphy gif picker final result image with a button to open gif picker, gif picker listing gifs with options to get trending gifs and search gifs.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qozesyg9nftxg8mcb464.png)

GitHub Gist: [https://gist.github.com/sarinmsari/e2a47f457a1b5924ba4e5791b954ca88](https://gist.github.com/sarinmsari/e2a47f457a1b5924ba4e5791b954ca88)