I'm using vue-fontawesome together with font-awesome-icon. This works great for "standalone" icons like so:
<font-awesome-icon :icon="icon" size="1x" /> .
But how can I use the fontawesome checkmark for an <input type="checkbox">
in the vue component way?
There is a way to look for css pseudo-elements:
FontAwesomeConfig = { searchPseudoElements: true };
This method is not recommended since it will examine existing markup and through CSS styling add inline SVG for pseudo-elements, which is slow.
I do not encourage this method so I will not explain how it works, if you're interested you can read more about it here.
Instead of using pseudo-elements, create a component for these checkboxes.
We will create a Single File Component called awesome-checkbox
.
AwesomeCheckbox.vue
<template>
<div :class="{'awesome-checkbox': true, [wrapperClassName]: !!wrapperClassName}"
:style="{ color: isChecked ? checkedColor : uncheckedColor }">
<input :id="id"
:name="name"
type="checkbox"
class="awesome-checkbox__input"
v-model="checkboxModel">
<label :for="id"
:style="{ cursor }"
class="awesome-checkbox__label"
@click="toggleCheck">
<font-awesome-icon :icon="isChecked ? checkedIcon : uncheckedIcon"
:size="size" />
</label>
</div>
</template>
<script>
import FontAwesomeIcon from '@fortawesome/vue-fontawesome';
import { faSquare, faCheckSquare } from '@fortawesome/fontawesome-free-solid';
/**
* Custom HTML <input> checkbox element using Font-Awesome-Icon 5 icons for visual effect.
*/
export default {
name: 'awesome-checkbox',
components: { FontAwesomeIcon },
props: {
/**
* A wrapper class other than default that provides extra manipulation from parent component.
*/
wrapperClassName: {
type: String,
default: null,
},
/**
* The name attribute for the checkbox input.
*/
name: {
type: String,
default: null,
},
/**
* The id attribute for the checkbox input.
*/
id: {
type: String,
default: null,
required: true,
},
/**
* The model directive value to create two-way data binding.
*/
model: {
type: Boolean,
default: null,
required: true,
},
/**
* The mouse cursor to display when the mouse pointer is over the Font-Awesome-Icon 5 element.
* Accepts any cursor CSS property value.
*/
cursor: {
type: String,
default: 'pointer',
},
/**
* The Font-Awesome-Icon 5 imported icon object used for the unchecked state.
*/
uncheckedIcon: {
type: Object,
default: () => faSquare,
},
/**
* The Font-Awesome-Icon 5 imported icon object used for the checked state.
*/
checkedIcon: {
type: Object,
default: () => faCheckSquare,
},
/**
* The Font-Awesome-Icon 5 icon size.
*/
size: {
type: String,
default: '1x',
},
/**
* The Font-Awesome-Icon 5 icon color used for the unchecked state.
*/
uncheckedColor: {
type: String,
default: 'inherit',
},
/**
* The Font-Awesome-Icon 5 icon color used for the checked state.
*/
checkedColor: {
type: String,
default: 'inherit',
},
},
data() {
return {
isChecked: !!this.model,
checkboxModel: this.model,
};
},
methods: {
emitModelValueUpdate() {
/**
* Update event.
*
* @event update
* @type {boolean}
*/
this.$emit('update:model', this.isChecked);
},
/**
* Gets called when the user clicks on the label element.
*/
toggleCheck() {
this.isChecked = !this.isChecked;
this.emitModelValueUpdate();
},
},
};
</script>
<style lang="scss" scoped>
.awesome-checkbox {
display: inline-flex;
&__label {
font-size: 1em; // Change Font-Awesome-Icon 5 icon size with css instead of predefined Font-Awesome-Icon 5 size prop.
}
&__input {
display: none; // Hide the HTML <input> element.
}
}
</style>
And use it in a parent component like so:
<template>
<div>
<awesome-checkbox :model.sync="acceptTerms"
checkedColor="#41B883"
uncheckedColor="#E0EAF1"
cursor="pointer"
size="1x"
id="my-awesome-checkbox"
name="acceptTerms"
:checkedIcon="faCheckSquare"
:uncheckedIcon="faSquare" />
</div>
</template>
<script>
import { faSquare, faCheckSquare } from '@fortawesome/fontawesome-free-solid';
import AwesomeCheckbox from '@/components/path/to/AwesomeCheckbox';
export default {
name: 'parent-component',
components: { AwesomeCheckbox },
data() {
return {
acceptTerms: false,
faSquare,
faCheckSquare,
};
},
};
</script>
<style lang="scss" scoped>
/* ... */
</style>
You can extend this component to your needs, like making the model
prop accept more than one type, like an Array instead of a boolean.
I just made this component for your question and have not tested it fully, please use it carefully.
Using all of Ricky's effort but in typescript for those who might be looking, as I was.
The Checkbox
<template>
<div :class="{'awesome-checkbox': true, [wrapperClassName]: !!wrapperClassName}"
:style="{ color: checked ? checkedColor : uncheckedColor }">
<input :id="id"
:name="name"
type="checkbox"
class="awesome-checkbox__input"
v-model="checked">
<label :for="id"
:style="{ cursor }"
class="awesome-checkbox__label"
@click="toggleCheck">
<font-awesome-icon :icon="checked ? checkedIcon : uncheckedIcon"
:size="size" />
</label>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { faSquare, faCheckSquare } from '@fortawesome/fontawesome-free-solid';
@Component
export default class Checkbox extends Vue {
@Prop({default: null})
wrapperClassName!: string;
@Prop({default: null})
name!: string;
@Prop({default: null, required: true})
id!: string;
@Prop({default: null, required: true})
model!: Boolean;
@Prop({default: 'pointer'})
cursor!: string;
@Prop({default: () => faSquare})
uncheckedIcon!: Object;
@Prop({default: () => faCheckSquare})
checkedIcon!: Object;
@Prop({default: '1x'})
size!: string;
@Prop({default: 'inherit'})
uncheckedColor!: string;
@Prop({default: 'inherit'})
ucheckedColor!: string;
private emitModelValueUpdate() {
/**
* Update event.
*
* @event update
* @type {boolean}
*/
this.$emit('update:model', this.$data.checked);
}
private toggleCheck() {
this.$data.checked = !this.$data.checked;
this.emitModelValueUpdate();
}
constructor() {
super();
}
public data() {
return {
checked: false,
};
}
}
</script>
<style lang="scss" scoped>
.awesome-checkbox {
display: inline-flex;
&__label {
font-size: 1em; // Change Font-Awesome-Icon 5 icon size with css instead of predefined Font-Awesome-Icon 5 size prop.
}
&__input {
display: none; // Hide the HTML <input> element.
}
}
</style>
The Parent
<template>
<div class="content">
<b-row>
<b-col>
<Checkbox />
</b-col>
</b-row>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import Checkbox from '@/components/forms/Checkbox.vue';
@Component({
components: {
Checkbox,
},
})
export default class DevHelper extends Vue {
@Prop() private msg!: string;
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With