Skip to content

Instantly share code, notes, and snippets.

@depsimon
Created March 5, 2019 10:41
Show Gist options
  • Save depsimon/66edd89939f6700c50b5946d4e129460 to your computer and use it in GitHub Desktop.
Save depsimon/66edd89939f6700c50b5946d4e129460 to your computer and use it in GitHub Desktop.
Avatar Picker with Vuetify in a Profile Form
.avatar-picker-avatar {
opacity: .5;
transition: all .1s ease-in-out;
&:hover, &.current {
opacity: 1;
}
}
<template>
<v-dialog :fullscreen="$vuetify.breakpoint.xs" width="500" transition="dialog-bottom-transition" v-model="show">
<v-card>
<v-toolbar dark color="primary">
<v-btn icon dark @click="show = false">
<v-icon>close</v-icon>
</v-btn>
<v-toolbar-title>Select an Avatar</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-layout row wrap v-if="avatars">
<v-flex
v-for="avatar in avatars"
:key="avatar.id"
xs4 sm3
d-flex>
<v-card tile flat class="d-flex">
<v-card-text class="d-flex">
<v-avatar
size="96"
@click="selectAvatar(avatar)"
class="avatar-picker-avatar"
:class="{ 'current': avatar.id === currentAvatar }">
<img :src="'/avatars/' + (avatar.path)">
</v-avatar>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</v-card>
</v-dialog>
</template>
<script>
export default {
props: {
currentAvatar: {
type: String,
required: true
},
value: Boolean
},
async mounted () {
await this.$store.dispatch('fetchAvatars')
},
computed: {
avatars () {
return this.$store.state.avatars
},
show: {
get () {
return this.value
},
set (value) {
this.$emit('input', value)
}
}
},
methods: {
selectAvatar (avatar) {
this.$emit('selected', avatar.id)
this.show = false
}
}
}
</script>
export const state = () => ({
avatars: {}
})
export const mutations = {
setAvatars (state, avatars) {
state.avatars = avatars
}
}
export const actions = {
fetchAvatars ({ commit, state }) {
if (Object.keys(state.avatars).length) {
return state.avatars
}
let avatars = {}
let files = require.context('~/static/avatars', true, /\.png$/i)
files.keys().map((key) => {
let id = key.split('/').pop().split('.')[0].substring(7).toUpperCase()
avatars[id] = {
path: key.split('/').pop(),
id: id
}
})
commit('setAvatars', avatars)
}
}
<template>
<v-container fluid>
<v-layout column>
<v-card>
<v-card-text>
<v-flex class="mb-4">
<v-avatar size="96" class="mr-4">
<img :src="'/avatars/avatar_' + (form.avatar.toLowerCase()) + '.png'" alt="Avatar">
</v-avatar>
<v-btn @click="openAvatarPicker">Change Avatar</v-btn>
</v-flex>
<v-text-field
v-model="form.firstName"
label="FirstName"></v-text-field>
<v-text-field
v-model="form.lastName"
label="Last Name"></v-text-field>
<v-text-field
v-model="form.contactEmail"
label="Email Address"></v-text-field>
</v-card-text>
<v-card-actions>
<v-btn color="primary" :loading="loading" @click.native="update">
<v-icon left dark>check</v-icon>
Save Changes
</v-btn>
</v-card-actions>
</v-card>
</v-layout>
<avatar-picker
v-model="showAvatarPicker"
:current-avatar="form.avatar"
@selected="selectAvatar"></avatar-picker>
</v-container>
</template>
<script>
import AvatarPicker from '~/components/AvatarPicker'
export default {
pageTitle: 'My Profile',
components: { AvatarPicker },
data () {
return {
loading: false,
form: {
firstName: 'John',
lastName: 'Doe',
contactEmail: '[email protected]',
avatar: 'MALE_CAUCASIAN_BLOND_BEARD'
},
showAvatarPicker: false
}
},
methods: {
openAvatarPicker () {
this.showAvatarPicker = true
},
selectAvatar (avatar) {
this.form.avatar = avatar
}
}
}
</script>
@Lingerew711
Copy link

where are static/avatars files?

@depsimon
Copy link
Author

@Lingerew711 Wherever your want as long as it's accessible by your app. In my case, ~ means the root folder of the the app, so the path is {root}/static/avatars/. You can have it in /public or wherever you want.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment