I am building a website using Vue JS 3 and Laravel and when I try and implement my Index.vue component I receive these errors:
[Vue warn]: Missing required prop: "label" [Vue warn]: Missing required prop: "isDisabled"
I am pretty sure they are defined correctly in both the parent:
Vue.component('biometricos', {
props: {
label: {
required: true,
type: String,
default: '',
},
className: {
type: String
},
isDisabled: {
required: true,
type: Boolean,
default: false
},
hours: Boolean,
minutes: Boolean,
}
});
and child:
props: {
label: {
required: true,
type: String,
default: '',
},
className: {
type: String
},
isDisabled: {
required: true,
type: Boolean,
default: false
},
hours: Boolean,
minutes: Boolean,
},
It might make sense to declare a label like this
<Component label="YourLabelHere" isDisabled="false"></Component>
Here is my full Index.vue file:
<script>
import * as actions from "../../../Config/ApiUrl";
import { TableHelpers } from "./TableHelpers";
export default {
name: "Biometricos",
mixins: [TableHelpers],
data() {
return {
momentInstance: moment(),
searchValue: '',
deleteLoader: false,
isAddEditModalActive: false,
deleteConformationModalActive: false,
selectedUrl: '',
tableId: '',
rowData: {},
time: null,
isRunning: false,
startTime: null,
times: [0, 0, 0, 0],
frameId: null,
options: {
name: 'position-table',
isAddEditModalActive: false,
url: `${actions.POSITION}/index`,
showHeader: true,
columns: [],
datatableWrapper: false,
showFilter: false,
showSearch: false,
showAction: false,
actions: [],
paginationType: "pagination",
rowLimit: 10,
orderBy: 'desc',
},
}
},
props: {
label: {
required: true,
type: String,
default: '',
},
className: {
type: String
},
isDisabled: {
required: true,
type: Boolean,
default: false
},
hours: Boolean,
minutes: Boolean,
},
created() {
this.options.columns = [...this.tableColumns];
},
mounted() {
setInterval(() => {
this.momentInstance = moment()
}, 1000)
},
watch: {
searchValue: function (value) {
if (value === '')
this.getSearchValue();
}
},
methods: {
getSearchValue() {
this.$emit('input', this.searchValue);
},
submit() {
this.$emit('submit');
},
start() {
if (this.isRunning) throw new Error('Stopwatch has already started.');
this.isRunning = true;
if (!this.startTime) this.startTime = performance.now();
this.$emit('start', this.startTime);
this.frameId = requestAnimationFrame(this.step);
},
lap(id) {
this.$emit('lap', performance.now(), this.time, id);
},
pause() {
this.isRunning = !this.isRunning
if (this.isRunning) {
this.startTime = performance.now()
this.calculate(performance.now())
this.frameId = requestAnimationFrame(this.step)
}
this.$emit('pause', this.isRunning, this.time)
},
stop() {
if (!this.isRunning) throw new Error('Stopwatch has not been started yet.');
this.isRunning = false;
this.startTime = null;
this.times = [0, 0, 0, 0];
this.$emit('stop', performance.now(), this.time);
cancelAnimationFrame(this.frameId);
},
reset() {
this.startTime = 0;
this.isRunning = false;
this.times = [0, 0, 0, 0];
this.time = this.formatTimes();
},
formatTimes(times = this.times) {
const hours = pad0(times[0], 2);
const minutes = pad0(times[1], 2);
const seconds = pad0(times[2], 2);
const milliseconds = pad0(Math.trunc(times[3] % 100), 2);
if (this.hours) {
return `${hours}:${minutes}:${seconds}:${milliseconds}`;
}
if (this.minutes) {
return `${minutes}:${seconds}:${milliseconds}`;
}
return `${seconds}:${milliseconds}`;
function pad0(value, count) {
let result = value.toString();
while (result.length < count) {
result = '0' + result;
--count;
}
return result;
}
},
step(timestamp) {
if (!this.isRunning) return;
this.calculate(timestamp);
this.startTime = timestamp;
this.time = this.formatTimes();
this.frameId = requestAnimationFrame(this.step);
},
calculate(timestamp) {
const diff = timestamp - this.startTime;
this.times[3] += diff / 10;
if (this.times[3] >= 100) {
this.times[3] -= 100;
this.times[2] += 1;
}
if (this.times[2] >= 60) {
this.times[2] -= 60;
this.times[1] += 1;
}
if (this.times[1] >= 60) {
this.times[1] -= 60;
this.times[0] += 1;
}
},
currentDate() {
return new Date().toLocaleDateString();
},
currentTime() {
return new Date().toLocaleTimeString();
},
clockIn() {
this.start();
// Get the current date and time
const currentDate = this.currentDate();
const currentTime = this.currentTime();
// Update the table data with the current date and time
const newIngreso = { permission_date: currentDate, ingreso: currentTime };
// Assuming the table data is an array under 'options' property
this.options.data.push(newIngreso);
// Emit an event to notify the parent component to update the table view
this.$emit('update-table', this.options.data);
// Open the description modal or do other tasks as needed
console.log('Clock In button clicked');
},
almorzar() {
this.pause();
const currentTime = this.currentTime();
const newAlmuerzo = { almuerzo: currentTime };
this.options.data.push(newAlmuerzo);
this.$emit('update-table', this.options.data);
},
regresar() {
this.pause();
const currentTime = this.currentTime();
const newRegreso = { regreso: currentTime };
this.options.data.push(newRegreso);
this.$emit('update-table', this.options.data);
},
clockOut() {
this.stop();
const currentTime = this.currentTime();
const newSale = { salido: currentTime };
this.options.data.push(newSale);
this.$emit('update-table', this.options.data);
this.reset();
// store time
// store total
// open description modal
},
openAddEditModal() {
this.isAddEditModalActive = true;
},
closeAddEditModal() {
$("#demo-add-edit-Modal").modal('hide');
this.isAddEditModalActive = false;
this.reSetData();
},
reSetData() {
this.rowData = {};
this.selectedUrl = '';
},
}
}
</script>
<style>
html,
body {
margin: 0;
padding: 0;
}
.content-wrapper {
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-wrap: wrap;
}
.left-side,
.right-side {
flex: 1;
width: 100%;
}
@media (max-width: 600px) {
.row {
flex-direction: column;
}
.left-side,
.right-side {
width: 100%;
}
.right-side {
order: 2;
margin-top: 20px;
}
.left-side {
order: 1;
}
.logo {
display: none;
}
}
.tele-panel {
display: flex;
flex-direction: column;
}
.header-title {
font-family: Poppins, sans-serif;
color: #555555;
}
.callout.calendar-day {
padding: .8rem 1.9rem;
margin-top: 10vh;
text-align: right;
}
.callout.calendar-day h1 {
margin: 0 1rem 0 0;
}
.callout.calendar-day h6 {
margin: 0;
}
.callout.calendar-day h1.light {
color: #555555;
}
.logo {
aspect-ratio: 1.85;
width: 200px;
margin: 0 auto;
}
.divider-line {
border-left: .1px solid rgba(0, 0, 0, 0.25);
height: 100%;
position: absolute;
left: 95%;
top: 0;
bottom: 0;
}
@media (max-width: 1300px) {
.divider-line {
display: none;
}
}
.timbres {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.timbres .btn-primary {
margin-right: 20px;
flex: 1;
}
</style>
<template>
<div class="content-wrapper">
<div class="row">
<div class="left-side col-sm-4">
<div class="tele-panel">
<h1 class="header-title display-4">TeleTrabajo</h1>
<div class="callout calendar-day">
<div class="grid-x">
<div class="shrink cell">
<h3 class="text-primary margin-left">{{ this.momentInstance.format('DD') }}
<h3 class="text-primary text d-inline"></h3>
</h3>
</div>
<div class="auto cell">
<h3>{{ this.momentInstance.format('[de] MMMM [de] ') }}
<h3 class="text-primary text d-inline"> {{ this.momentInstance.format('YYYY') }}
</h3>
</h3>
<h3>{{ this.momentInstance.format('dddd ') }}
<h3 class="text-primary text d-inline"> {{ this.momentInstance.format('HH:mm:ss') }}
</h3>
</h3>
</div>
</div>
</div>
<img loading="lazy"
srcSet="https://cdn.builder.io/api/v1/image/assets/TEMP/7d7c128b9d97cdbc97e3f753e10d62e1d1922d448a7d54a60a1e245750a1eb93?apiKey=a927cef3079c4be4b43e485687f422e0&width=100 100w, https://cdn.builder.io/api/v1/image/assets/TEMP/7d7c128b9d97cdbc97e3f753e10d62e1d1922d448a7d54a60a1e245750a1eb93?apiKey=a927cef3079c4be4b43e485687f422e0&width=200 200w, https://cdn.builder.io/api/v1/image/assets/TEMP/7d7c128b9d97cdbc97e3f753e10d62e1d1922d448a7d54a60a1e245750a1eb93?apiKey=a927cef3079c4be4b43e485687f422e0&width=400 400w, https://cdn.builder.io/api/v1/image/assets/TEMP/7d7c128b9d97cdbc97e3f753e10d62e1d1922d448a7d54a60a1e245750a1eb93?apiKey=a927cef3079c4be4b43e485687f422e0&width=800 800w, https://cdn.builder.io/api/v1/image/assets/TEMP/7d7c128b9d97cdbc97e3f753e10d62e1d1922d448a7d54a60a1e245750a1eb93?apiKey=a927cef3079c4be4b43e485687f422e0&width=1200 1200w, https://cdn.builder.io/api/v1/image/assets/TEMP/7d7c128b9d97cdbc97e3f753e10d62e1d1922d448a7d54a60a1e245750a1eb93?apiKey=a927cef3079c4be4b43e485687f422e0&width=1600 1600w, https://cdn.builder.io/api/v1/image/assets/TEMP/7d7c128b9d97cdbc97e3f753e10d62e1d1922d448a7d54a60a1e245750a1eb93?apiKey=a927cef3079c4be4b43e485687f422e0&width=2000 2000w, https://cdn.builder.io/api/v1/image/assets/TEMP/7d7c128b9d97cdbc97e3f753e10d62e1d1922d448a7d54a60a1e245750a1eb93?apiKey=a927cef3079c4be4b43e485687f422e0&"
class="logo" />
</div>
<div class="divider-line"></div>
</div>
<div class="right-side col-sm-8">
<div class="timbres mt-3 mb-3">
<app-button :label="$t('Ingreso')" class-name="btn-primary" :is-disabled="false"
@click="clockIn" />
<app-button :label="$t('Almuerzo')" class-name="btn-primary" :is-disabled="false"
@click="almorzar" />
<app-button :label="$t('Regreso')" class-name="btn-primary" :is-disabled="false"
@click="regresar" />
<app-button :label="$t('Salido')" class-name="btn-primary" :is-disabled="false"
@click="openAddEditModal" />
<div class="search d-flex justify-content-end">
<div class="form-group form-group-with-search d-flex">
<span :key="'search'" class="form-control-feedback">
<app-icon name="search" />
</span>
<input type="text" class="form-control" v-model="searchValue" :placeholder="$t('search')"
@keydown.enter.prevent="getSearchValue" />
</div>
</div>
</div>
<app-table :id="'biometricos-table'" :options="options" />
<app-position-modal v-if="isAddEditModalActive" :table-id="tableId" :selected-url="selectedUrl"
@close-modal="closeAddEditModal" />
</div>
<!-- <div class="buttons-section col-sm-6">
<div class="horas-square ">horas</div>
</div> -->
</div>
</div>
</template>
Any ideas on why this might be happening are much