Привет, ребята, я уже давно занимаюсь этим. Я пытаюсь отфильтровать свои шаблоны по категориям и ключевым словам с помощью кнопок.У меня есть приложение vuejs, которое использует метод фильтра.Это работает очень хорошо, за исключением случаев, когда у меня не выбрано ни одного ключевого слова и я начал выбирать несколько категорий.Например, у меня есть шаблон с именем test, который связан как с категорией спорта, так и с категорией отдыха.Когда оба выбраны, я получаю дубликат.Я очень близок к этому, я только что застрял в этой части в течение недели.Я понимаю, что это много кода, но он чистый, читаемый и не имеет смысла, если я не дам вам обзор.
Вот скрипка с кодом https://jsfiddle.net/rshba6jz/
Вот интерфейсcode
<?php require_once('header.php');
require_once('database.php');
if ($result = $mysqli->query("SELECT t.*, GROUP_CONCAT(c.category) categories, GROUP_CONCAT(k.keyword) keywords FROM dataclayTemplates t LEFT JOIN dataclayCategoryLink cl JOIN dataclayCategories c ON cl.categoryId=c.id ON t.id=cl.templateId LEFT JOIN dataclayKeywordLink kl JOIN dataclayKeywords k ON kl.keywordId=k.id ON t.id=kl.templateId GROUP BY t.id"))
{
while($row = $result->fetch_array(MYSQLI_ASSOC)) {
if($row["categories"] == null) {
$row["categoryArray"] = [];
} else {
$row["categoryArray"] = array_unique(explode(",",$row["categories"]));
}
unset($row["categories"]);
if($row["keywords"] == null) {
$row["keywordArray"] = [];
} else {
$row["keywordArray"] = array_unique(explode(",",$row["keywords"]));
}
unset($row["keywords"]);
$templateArray[] = $row;
}
}
$result->close();
$categoryArray = array();
if ($result = $mysqli->query("SELECT category FROM dataclayCategories;"))
{
while($row = $result->fetch_array(MYSQLI_ASSOC)) {
array_push($categoryArray, $row['category']);
}
}
$result->close();
$keywordArray = array();
if ($result = $mysqli->query("SELECT keyword FROM dataclayKeywords;"))
{
while($row = $result->fetch_array(MYSQLI_ASSOC)) {
array_push($keywordArray, $row['keyword']);
}
}
$result->close();
$mysqli->close();
?>
<div v-cloak id="templates" class="container content">
<div class="col-lg-3 visible-lg-block hidden-md" id="SearchTemplatesLargeContainer">
<form role="form" role="form" onsubmit="return false">
<div class="form-group">
<label for="searchBar">Search</label>
<input v-model="searchQuery" type="text" placeholder="Search Tempates" id="searchBar" autocomplete="off" class="form-control">
</div>
<div class="form-group">
<label>Sort By</label>
<select v-model="sortBy" class="form-control">
<option value="renderTime">Render Time</option>
<option value="az">A-Z</option>
<option value="dateAdded">Newest</option>
</select>
</div>
<div class="form-group">
<h5>Categories</h5>
<div v-for="category in categories" :class="category + 'Button'" v-on:click.prevent="selectCategory(category)" class="btn btn-default categoryButton">
{{category}}
</div>
</div>
<div class="form-group">
<h5>Keywords</h5>
<div v-for="keyword in keywords" :class="keyword + 'Button'" v-on:click.prevent="selectKeyword(keyword)" class="btn btn-default categoryButton">
{{keyword}}
</div>
</div>
</form>
</div>
<!--end lg template menu col-lg-3-->
<!--search templates modal-->
<div class="modal fade" role="dialog" id="searchTemplatesModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">X</button>
<h2 class="modal-title">Search Templates</h2>
<!--end .modal-title-->
</div>
<!--end modal-header-->
<div class="modal-body">
<form role="form">
<div class="form-group">
<label>Search</label>
<input v-model="searchQuery" type="text" placeholder="Search Tempates" autocomplete="off" class="form-control">
</div>
<!--.end searchQuery-->
<div class="form-group">
<label>Sort By</label>
<select v-model="sortBy" class="form-control">
<option value="renderTime">Render Time</option>
<option value="az">A-Z</option>
<option value="dateAdded">Newest</option>
</select>
</div>
<!--end sortBy-->
<div class="form-group">
<h5>Categories</h5>
<div v-for="category in categories" :class="category + 'Button'" v-on:click.prevent="selectCategory(category)" class="btn btn-default categoryButton">
{{category}}
</div>
</div>
<!--end categorys-->
<div class="form-group">
<h5>Keywords</h5>
<div v-for="keyword in keywords" :class="keyword + 'Button'" v-on:click.prevent="selectKeyword(keyword)" class="btn btn-default categoryButton">
{{keyword}}
</div>
</div>
<!--end keywords-->
</form>
</div>
<!--end .modal-body-->
<div class="modal-footer">
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal">Search</button>
</div>
<!--end .modal-footer-->
</div>
<!--end .modal-content-->
</div>
<!--end .modal-dialog-->
</div>
<!-- end search templates modal-->
<div class="col-lg-9 col-md-12 col-sm-12 col-xs-12">
<div class="row">
<h1 class="mainHeading">Templates</h1>
</div>
<div class="row">
<div v-cloak v-bind:key="template.itemId + '_' + index" v-for="(template, index) in searchResults" class="col-md-4">
<div class="card">
<video muted :src="mysource" controls preload="none" controlsList="nodownload nofullscreen" :poster="mysouce" loop="loop"></video>
<div class="card-body">
<p class="card-title">{{template.itemName}}</p>
<!--end card-title-->
<p v-show="displayCount==0" class="card-text">Please create a display to customize</p>
<!--end user has no display card-text-->
<p v-show="displayCount>0" class="card-text">Custom Text, Custom Colors, Upload Logo</p>
<!--end user has display card text-->
<p class="card-text">{{template.renderTime}} minutes</p>
<a href="#" v-show="loggedIn==true && displayCount>0" class="btn btn-primary btn-block">Customize</a>
<!--logged in and has display button-->
<a href="#" v-show="loggedIn==false" class="btn btn-primary btn-block" disabled>Customize</a>
<!--not logged in button-->
<a href="profile.php?showAddDisplayForm=1" v-show="loggedIn==true && displayCount==0" class="btn btn-primary btn-block">Create A Display</a>
</div>
<!--end card-body-->
</div>
<!--end card-->
</div>
<!-- end col-md-4-->
</div>
<!--end row-->
</div>
<!--end col-lg-9 col-md-12 col-sm-12 col-xs-12-->
</div>
<!--end templates app-->
<script>
var app = new Vue({
el: '#templates',
data: {
loggedIn: false,
displayCount:'<?php if(isset($_SESSION['displayCount'])){echo $_SESSION['displayCount'];} else{echo 0;}?>',
searchQuery:'',
templateArray: <?php echo json_encode($templateArray); ?>,
filteredTemplateArray: <?php echo json_encode($templateArray); ?>,
categories: <?php echo json_encode($categoryArray); ?>,
selectedCategories: [],
keywords: <?php echo json_encode($keywordArray); ?>,
selectedKeywords: [],
sortBy: ''
},
computed: {
searchResults: function(){
return this.filteredTemplateArray.filter((template)=>{
return template.itemName.toLowerCase().includes(this.searchQuery.toLowerCase());
})
}
},
created: function() {
this.loggedIn=<?php if(isset($_SESSION['loggedIn'])){echo $_SESSION['loggedIn'];} else {echo 0;}?>;
this.filteredTemplateArray.sort(function(a,b) {
return parseInt(a.renderTime) - parseInt(b.renderTime);
});
},
watch: {
sortBy: function() {
if(this.sortBy == "az") {
this.filteredTemplateArray.sort(function(a,b) {
if(a.itemName > b.itemName) {
return 1;
}
if(a.itemName < b.itemName) {
return -1;
}
return 0;
});
}
if(this.sortBy == "dateAdded") {
this.filteredTemplateArray.sort(function(a,b) {
if(a.dateAdded < b.dateAdded) {
return 1;
}
if(a.dateAdded > b.dateAdded) {
return -1;
}
return 0;
});
}
if(this.sortBy == "renderTime") {
this.filteredTemplateArray.sort(function(a,b) {
return parseInt(a.renderTime) - parseInt(b.renderTime);
});
}
}
},
mounted: function(){
this.sortBy="renderTime";
},
methods: {
filter: function() {
var filteredCategoryArray = [];
var filteredKeywordArray = [];
if(this.selectedCategories.length != 0) {
for(var i = 0; i < this.templateArray.length; i++) {
for(var j = 0; j < this.selectedCategories.length; j++ ) {
for(var k = 0; k < this.templateArray[i].categoryArray.length; k++ ) {
if(this.templateArray[i].categoryArray[k] == this.selectedCategories[j]) {
console.log(this.templateArray[i].categoryArray[k]);
console.log(this.selectedCategories[j]);
var arrayDuplicate = false;
for(var l = 0; l < filteredKeywordArray.length; l++) {
if(filteredCategoryArray[l].id == this.templateArray[i].id) {
arrayDuplicate = true;
}
}
if(arrayDuplicate == false) {
filteredCategoryArray.push(this.templateArray[i]);
}
}
}
}
}
} else {
for(var i = 0; i < this.templateArray.length; i++){
filteredCategoryArray.push(this.templateArray[i]);
}
}
if(this.selectedKeywords.length != 0) {
for(var i = 0; i < filteredCategoryArray.length; i++) {
for(var j = 0; j < this.selectedKeywords.length; j++ ) {
for(var k = 0; k < filteredCategoryArray[i].keywordArray.length; k++ ) {
if(filteredCategoryArray[i].keywordArray[k] == this.selectedKeywords[j]) {
var arrayDuplicate = false;
for(var l = 0; l < filteredKeywordArray.length; l++) {
if(filteredKeywordArray[l].id == filteredCategoryArray[i].id) {
arrayDuplicate = true;
}
}
if(arrayDuplicate == false) {
filteredKeywordArray.push(filteredCategoryArray[i]);
}
}
}
}
}
} else {
for(var i = 0; i < filteredCategoryArray.length; i++){
filteredKeywordArray.push(filteredCategoryArray[i]);
}
}
if(this.sortBy == "az") {
filteredKeywordArray.sort(function(a,b) {
if(a.itemName > b.itemName) {
return 1;
}
if(a.itemName < b.itemName) {
return -1;
}
return 0;
});
}
if(this.sortBy == "dateAdded") {
filteredKeywordArray.sort(function(a,b) {
if(a.dateAdded < b.dateAdded) {
return 1;
}
if(a.dateAdded > b.dateAdded) {
return -1;
}
return 0;
});
}
if(this.sortBy == "renderTime") {
filteredKeywordArray.sort(function(a,b) {
return parseInt(a.renderTime) - parseInt(b.renderTime);
});
}
this.filteredTemplateArray = filteredKeywordArray;
$('html,body').scrollTop(0);
},
selectCategory: function(category) {
var categoryButton = $('.' + category + 'Button');
categoryButton.toggleClass('categoryButtonSelected');
if(this.selectedCategories.includes(category)){
var array = [];
for(var i = 0; i < this.selectedCategories.length; i++) {
if(this.selectedCategories[i] != category) {
array.push(this.selectedCategories[i]);
}
}
this.selectedCategories = array;
} else {
this.selectedCategories.push(category);
}
this.filter();
},
selectKeyword: function(keyword) {
var categoryButton = $('.' + keyword + 'Button');
categoryButton.toggleClass('categoryButtonSelected');
if(this.selectedKeywords.includes(keyword)){
var array = [];
for(var i = 0; i < this.selectedKeywords.length; i++) {
if(this.selectedKeywords[i] != keyword) {
array.push(this.selectedKeywords[i]);
}
}
this.selectedKeywords = array;
} else {
this.selectedKeywords.push(keyword);
}
this.filter();
}
}
});
</script>
У меня есть, когда щелкают по шаблону, это то, что передается в мой FilterTemplateArray в Инспекторе vue.Если есть несколько элементов с одинаковым идентификатором (в данном случае 223, я бы хотел, чтобы они были отфильтрованы, чтобы не было дубликатов. Он отлично работает с ключевыми словами, но не работает с категориями. Я уверен, что это просто, но я действительно застрял и некоторая помощьбыло бы здорово.
filteredTemplateArray:Array[1]
0:Object
categoryArray:Array[3]
0:"Misc"
1:"Holiday"
2:"Sports"
dateAdded:"2018-10-01 17:54:22"
id:"233"
itemId:"fb41a01641bb2e769db412d3b21c2e3e"
itemName:"test"
keywordArray:Array[2]
0:"Snow"
1:"LensFlare"
projectPath:"M:/Projects/Generics/uploads/testLocation"
renderTime:"4"
stillImageLocation:"0.13"
tested:"0"
thumbName:"TEST"