我目前正在开发我们的 capstone 项目,该项目在 laravel 上运行作为我的框架,以 tailwind 作为我的 css,我偶然发现了一个我仍然无法理解的错误。
这是我的代码的第 1 块,它在可搜索的下拉列表中显示我的数据库中活动的校园:
<div class="flex-grow">
<label for="campus" class="block mb-2 text-sm font-medium">Campus</label>
<div x-data="selectAcademic()" x-init="fetchCampuses()" class="w-full flex flex-col items-center relative">
<div class="w-full">
<div @click.away="close()" class="p-1 bg-white flex border border-gray-300 rounded-lg">
<input
id="campus"
x-model="filter"
@click="open()"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@keydown.enter.stop.prevent="selectCampusOption()"
@keydown.arrow-up.prevent="focusPrevCampusOption()"
@keydown.arrow-down.prevent="focusNextCampusOption()"
class="p-1 px-2 appearance-none outline-none w-full text-gray-800"
placeholder="Select Campus"
x-bind:value="selectedCampusName()">
<div class="text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-300">
<button @click="toggle()" class="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline x-show="!isOpen()" points="18 15 12 20 6 15"></polyline>
<polyline x-show="isOpen()" points="18 15 12 9 6 15"></polyline>
</svg>
</button>
</div>
</div>
</div>
<div x-show="isOpen()" class="my-2 absolute shadow bg-white top-100 z-40 w-full lef-0 rounded max-h-select overflow-y-auto svelte-5uyqqj">
<div class="flex flex-col w-full">
<template x-for="(campusOption, index) in filteredCampusOptions()" :key="index">
<div @click="onOptionCampusClick(index)" :class="classCampusOption(campusOption.campus, index)" :aria-selected="focusedCampusOptionIndex === index">
<div class="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-facilityEaseSecondary hover:bg-blue-200">
<div class="w-full items-center flex">
<div class="mx-2 -mt-1"><span x-text="campusOption.campus"></span>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</div>
@if($errors->has('campus'))
<div class="text-facilityEaseSecondary font-bold italic text-xs">{{ $errors->first('campus') }}</div>
@endif
</div>
这是块 2,其中当用户在块 1 上选择特定校园时,该块应依赖于在块 1 上选择的 ID:
<div class="flex-grow">
<label for="college" class="block mb-2 text-sm font-medium">College</label>
<div x-data="selectAcademic()" x-init="fetchColleges($)" class="w-full flex flex-col items-center relative">
<div class="w-full">
<div @click.away="close()" class="p-1 bg-white flex border border-gray-300 rounded-lg">
<input
id="college"
x-model="filter"
@click="open()"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@keydown.enter.stop.prevent="selectCollegeOption()"
@keydown.arrow-up.prevent="focusPrevCollegeOption()"
@keydown.arrow-down.prevent="focusNextCollegeOption()"
class="p-1 px-2 appearance-none outline-none w-full text-gray-800"
placeholder="Select College"
x-bind:value="selectedCollegeName()">
<div class="text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-300">
<button @click="toggle()" class="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline x-show="!isOpen()" points="18 15 12 20 6 15"></polyline>
<polyline x-show="isOpen()" points="18 15 12 9 6 15"></polyline>
</svg>
</button>
</div>
</div>
</div>
<div x-show="isOpen()" class="my-2 absolute shadow bg-white top-100 z-40 w-full lef-0 rounded max-h-select overflow-y-auto svelte-5uyqqj">
<div class="flex flex-col w-full">
<template x-for="(collegeOption, index) in filteredCollegeOptions()" :key="index">
<div @click="onOptionCollegeClick(index)" :class="classCollegeOption(collegeOption.college, index)" :aria-selected="focusedCollegeOptionIndex === index">
<div class="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative hover:border-facilityEaseSecondary hover:bg-blue-200">
<div class="w-full items-center flex">
<div class="mx-2 -mt-1"><span x-text="collegeOption.college"></span>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</div>
@if($errors->has('college'))
<div class="text-facilityEaseSecondary font-bold italic text-xs">{{ $errors->first('college') }}</div>
@endif
</div>
现在,块 2 没有显示任何内容。后端可以工作,虽然我可以无缝获取我的数据,但它不会显示在我的视图上。
这里是处理此操作方法的 javascript 文件:
function selectAcademic() {
return {
filter: '',
show: false,
selected: null,
focusedCampusOptionIndex: null,
focusedCollegeOptionIndex: null,
campusOptions: null,
collegeOptions: null,
selectedCampusID: null,
computed: {
selectedCampus() {
return this.selected ? this.selected.campus : this.filter;
},
selectedCampusId: {
get() {
return this.selected ? this.selected.id : 0;
},
set(campusID) {
if (this.selected) {
this.selected.id = campusID;
}
}
},
},
close() {
this.show = false;
this.focusedCampusOptionIndex = this.selected ? this.focusedCampusOptionIndex : null;
this.focusedCollegeOptionIndex = this.selected ? this.focusedCollegeOptionIndex : null;
},
open() {
this.show = true;
this.filter = '';
},
toggle() {
if (this.show) {
this.close();
} else {
this.open()
}
},
isOpen() { return this.show === true },
selectedCampusName() { return this.selected ? this.selected.campus : this.filter; },
selectedCollegeName() { return this.selected ? this.selected.college : this.filter; },
classCampusOption(id, index) {
const isSelected = this.selected ? (id == this.selected.campus) : false;
const isFocused = (index == this.focusedCampusOptionIndex);
return {
'cursor-pointer w-full border-gray-100 border-b hover:bg-blue-50': true,
'bg-blue-100': isSelected,
'bg-blue-50': isFocused
};
},
classCollegeOption(id, index) {
const isSelected = this.selected ? (id == this.selected.college) : false;
const isFocused = (index == this.focusedCollegeOptionIndex);
return {
'cursor-pointer w-full border-gray-100 border-b hover:bg-blue-50': true,
'bg-blue-100': isSelected,
'bg-blue-50': isFocused
};
},
async fetchCampuses() {
console.log('Fetching Campus options...');
await fetch('/getCampuses')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();`enter code here`
})
.then(data => {
console.log('Campus data:', data);
this.campusOptions = data;
})
.catch(error => {
console.error('Error fetching campus data:', error);
});
},
async fetchColleges(selectedCampusID) {
selectedCampusID = this.selectedCampusId;
console.log('Fetching colleges by campus...');
console.log('Fetching colleges for Campus: ', selectedCampusID);
await fetch(`/getCollegesByCampus/${selectedCampusID}`)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log('College data:', data);
this.collegeOptions = data;
})
.catch(error => {
console.error('Error fetching college data:', error);
});
},
filteredCampusOptions() {
if (!this.campusOptions) {
return [];
}
console.log('Displaying filtered campus options: ', this.campusOptions);
return this.campusOptions.filter(campusOption => {
return campusOption && campusOption.campus && campusOption.campus.toLowerCase().indexOf(this.filter) > -1;
});
},
filteredCollegeOptions() {
if (!this.collegeOptions) {
return [];
}
console.log('Displaying filtered college options:', this.collegeOptions);
return this.collegeOptions.filter(collegeOption => {
return collegeOption && collegeOption.college && collegeOption.college.toLowerCase().indexOf(this.filter) > -1;
});
},
async onOptionCampusClick(index) {
this.focusedCampusOptionIndex = index;
await this.selectCampusOption();
await this.fetchColleges();
await this.filteredCollegeOptions();
},
async onOptionCollegeClick(index) {
this.focusedCollegeOptionIndex = index;
this.selectCollegeOption();
},
async selectCampusOption() {
if (!this.isOpen()) {
return;
}
this.focusedCampusOptionIndex = this.focusedCampusOptionIndex ?? 0;
const selected = this.filteredCampusOptions()[this.focusedCampusOptionIndex]
if (this.selected && this.selected.campus == selected.campus) {
this.filter = '';
this.selected = null;
this.selectedCampusId = null;
}
else {
this.selected = selected;
this.selectedCampusId = selected.id;
console.log('Selected:', this.selected);
console.log('Selected Campus ID:', this.selectedCampusId);
// await this.fetchColleges();
// await this.filteredCollegeOptions();
}
this.close();
},
selectCollegeOption() {
if (!this.isOpen()) {
return;
}
this.focusedCollegeOptionIndex = this.focusedCollegeOptionIndex ?? 0;
const selected = this.filteredCollegeOptions()[this.focusedCollegeOptionIndex]
if (this.selected && this.selected.college == selected.college) {
this.filter = '';
this.selected = null;
}
else {
this.selected = selected;
}
this.close();
},
focusPrevCampusOption() {
if (!this.isOpen()) {
return;
}
const optionsNum = Object.keys(this.filteredCampusOptions()).length - 1;
if (this.focusedCampusOptionIndex > 0 && this.focusedCampusOptionIndex <= optionsNum) {
this.focusedCampusOptionIndex--;
}
else if (this.focusedCampusOptionIndex == 0) {
this.focusedCampusOptionIndex = optionsNum;
}
},
focusPrevCollegeOption() {
if (!this.isOpen()) {
return;
}
const optionsNum = Object.keys(this.filteredCollegeOptions()).length - 1;
if (this.focusedCollegeOptionIndex > 0 && this.focusedCollegeOptionIndex <= optionsNum) {
this.focusedCollegeOptionIndex--;
}
else if (this.focusedCollegeOptionIndex == 0) {
this.focusedCollegeOptionIndex = optionsNum;
}
},
focusNextCampusOption() {
const optionsNum = Object.keys(this.filteredCampusOptions()).length - 1;
if (!this.isOpen()) {
this.open();
}
if (this.focusedCampusOptionIndex == null || this.focusedCampusOptionIndex == optionsNum) {
this.focusedCampusOptionIndex = 0;
}
else if (this.focusedCampusOptionIndex >= 0 && this.focusedCampusOptionIndex < optionsNum) {
this.focusedCampusOptionIndex++;
}
},
focusNextCollegeOption() {
const optionsNum = Object.keys(this.filteredCollegeOptions()).length - 1;
if (!this.isOpen()) {
this.open();
}
if (this.focusedCollegeOptionIndex == null || this.focusedCollegeOptionIndex == optionsNum) {
this.focusedCollegeOptionIndex = 0;
}
else if (this.focusedCollegeOptionIndex >= 0 && this.focusedCollegeOptionIndex < optionsNum) {
this.focusedCollegeOptionIndex++;
}
},
}
}
PS:我刚刚开始了解 alpine.js,代码是我从以下链接获得的模板:https://codepen.io/dixie0704/pen/jOVxGXL)
这些是我期望在视图中看到的数据,我直接播种这些值以查看它是否会显示:
['collegeID' => 2, 'college' => 'College of Technology', 'dean' => 'Ruvel J. Cuasito', 'status' => 1, 'created_by' => 'Administrator-Seeder', 'created_at' => $currentTimestamp, 'updated_at' => $currentTimestamp],
['collegeID' => 2, 'college' => 'College of Engineering and Architecture', 'dean' => 'Lory Liza D. Bulay-Og', 'status' => 1, 'created_by' => 'Administrator-Seeder', 'created_at' => $currentTimestamp, 'updated_at' => $currentTimestamp],
['collegeID' => 2, 'college' => 'College of Science and Mathematics', 'dean' => 'Maria Luisa B. Salingay', 'status' => 1, 'created_by' => 'Administrator-Seeder', 'created_at' => $currentTimestamp, 'updated_at' => $currentTimestamp],
['collegeID' => 2, 'college' => 'College of Science and Technology Education', 'dean' => 'Grace S. Pimentel', 'status' => 1, 'created_by' => 'Administrator-Seeder', 'created_at' => $currentTimestamp, 'updated_at' => $currentTimestamp],
['collegeID' => 2, 'college' => 'College of Information Technology and Computing', 'dean' => 'Love Jhoye M. Raboy', 'status' => 1, 'created_by' => 'Administrator-Seeder', 'created_at' => $currentTimestamp, 'updated_at' => $currentTimestamp],
['collegeID' => 2, 'college' => 'Senior High School Department', 'dean' => 'Kristiane Pagurayan', 'status' => 1, 'created_by' => 'Administrator-Seeder', 'created_at' => $currentTimestamp, 'updated_at' => $currentTimestamp]
其实我现在明白我的问题了。我从来没有理解过 alpine.js。更多的是代码的理论方面。我试图让它做一些不应该做的事情。这是我的错误。