Help implement the filtering of the existing list.

The problem is that after changing the corresponding select or checkbox, the dispalyCars method each time must draw the required number of elements with the cars-list__item class in the DOM.

 var dataController = (function() { var cars = [{ brand: 'Toyota', year: 2012, price: 600000, owners: 2, features: { transmission: 'auto', ac: true } }, { brand: 'Audi', year: 2002, price: 350000, owners: 3, features: { transmission: 'manual', ac: false } }, { brand: 'Ford', year: 2015, price: 500000, owners: 1, features: { transmission: 'auto', ac: true } }, { brand: 'Volkswagen', year: 1992, price: 99999, owners: 6, features: { transmission: 'manual', ac: false } }, { brand: 'Volkswagen', year: 2005, price: 450000, owners: 3, features: { transmission: 'manual', ac: true } }, { brand: 'Toyota', year: 2017, price: 900000, owners: 1, features: { transmission: 'auto', ac: true } }, { brand: 'BMW', year: 2010, price: 750000, owners: 3, features: { transmission: 'auto', ac: true } }, { brand: 'Ford', year: 2012, price: 520000, owners: 3, features: { transmission: 'auto', ac: true } }, { brand: 'Audi', year: 2000, price: 250000, owners: 5, features: { transmission: 'manual', ac: false } }, { brand: 'Subaru', year: 2013, price: 750000, owners: 1, features: { transmission: 'auto', ac: true } }, ]; return { getData: function() { return cars; } } })(); var UIcontroller = (function() { return { dispalyCars: function(carsList) { var carsBlock = document.querySelector('.cars-list'); var fragment = document.createDocumentFragment(); for (var i = 0; i < carsList.length; i++) { if (carsList[i].features.transmission === 'auto') { carsList[i].features.transmission = 'автомат'; } else { carsList[i].features.transmission = 'механическая'; }; if (carsList[i].features.ac === true) { carsList[i].features.ac = 'да'; } else { carsList[i].features.ac = 'нет'; }; var newCar = document.createElement('li'); newCar.className = 'cars-list__item'; newCar.textContent = 'Марка: ' + carsList[i].brand + ', Год выпуска: ' + carsList[i].year + ', Цена: ' + carsList[i].price + ' руб. ' + 'Собственников по ПТС: ' + carsList[i].owners + '. Дополнительно ' + '(' + 'коробка: ' + carsList[i].features.transmission + ', кондиционер: ' + carsList[i].features.ac + ')'; fragment.appendChild(newCar); } carsBlock.appendChild(fragment); } } })(); var controller = (function(dataCtrl, UICtrl) { // Получить массив с данными var carsList = dataCtrl.getData(); // Отрисовать список авто UICtrl.dispalyCars(carsList); })(dataController, UIcontroller); 
 .cars-list { padding: 0; margin: 0; min-height: 360px; } .cars-list__item { background-color: rgba(64, 161, 241, 0.753); box-sizing: border-box; width: 1000px; height: 30px; margin-top: 5px; margin-bottom: 5px; padding-top: 5px; padding-left: 5px; border-radius: 10px; list-style: none; } .filter { background-color: silver; width: 1000px; height: 30px; margin-top: 20px; padding-top: 5px; padding-left: 5px; border-radius: 10px; } 
 <div class="main"> <ul class="cars-list"></ul> <form action="#" class="filter" autocomplete="off"> <select name="barnd" id="brand-type" class="filter__brand"> <option value="any" selected>Любaя марка</option> <option value="toyota">Toyota</option> <option value="audi">Audi</option> <option value="ford">Ford</option> <option value="volkswagen">Volkswagen</option> <option value="bmw">BMW</option> <option value="subaru">Subaru</option> </select> <select name="year" id="cars-year" class="filter__year"> <option value="any" selected>Любой год выпуска</option> <option value="1">до 2000 года</option> <option value="2">до 2010 года</option> <option value="3">после 2010 года</option> </select> <select name="price" id="cars-price" class="filter__price"> <option value="any" selected>Любая цена</option> <option value="low">до 100000&#x20bd;</option> <option value="middle">100000 - 500000&#x20bd;</option> <option value="high">от 500000&#x20bd;</option> </select> <select name="owners" id="cars-owners" class="filter__owners"> <option value="any" selected>Любое число собственников</option> <option value="1">Один</option> <option value="2">Два</option> <option value="3">Три и более</option> </select> <input type="checkbox" name="features" value="auto" id="transmisson"> <label class="feature feature--auto" for="transmisson">Автоматическая коробка передач</label> <input type="checkbox" name="features" value="yes" id="conditioner"> <label class="feature feature--conditioner" for="conditioner">Кондиционер</label> </form> </div> 

  • It's not entirely clear why they considered the question a duplicate - russian-stan
  • If you need to filter the array - you can use the filter function, - this is exactly in duplicate and indicated. - Grundy
  • @Grundy there are several answers and part of one of them seems to be answering this question. This is not at all obvious. I propose here to write an answer specifically about filtering, and there give a link here. - Nick Volynkin
  • @NickVolynkin, somehow controversial. - Grundy

2 answers 2

If you need to filter an array, you can use the filter function.

 var filtered = carsList.filter(car => condition1 && condition2 && ...) 

Where instead of conditionN , the required properties are checked in accordance with the selected elements in the select.

after filtering you just need to transfer the resulting array to the UICtrl.dispalyCars function. It should be noted that this function does not pre- clear the .cars-list block, which can lead to duplication of elements. Therefore, it must either be added to the function itself, or done before calling it.

The filtering itself should be done in the change handlers of the necessary checkboxes and checkboxes.

  • That is exactly what I did when I figured out myself when the branch was considered a duplicate, but now the question arose how to do so in order to filter the check boxes if there are, say, not two, but much more - russian-stan
  • @ russian-stan, and what's the difference? The principle is the same. - Grundy
  • I wrote the code above as an answer to my own question, the principle is the same, but listing the check-boxes by indices is somehow not very good - russian-stan

In general, it works, but there is only the need to make filtering by check-boxes more universal in case there will be much more than 2

 var dataController = (function() { var cars = [{ brand: 'Toyota', year: 2012, price: 600000, owners: 2, features: { transmission: 'auto', ac: true } }, { brand: 'Audi', year: 2002, price: 350000, owners: 3, features: { transmission: 'manual', ac: false } }, { brand: 'Ford', year: 2015, price: 500000, owners: 1, features: { transmission: 'auto', ac: true } }, { brand: 'Volkswagen', year: 1992, price: 99999, owners: 6, features: { transmission: 'manual', ac: false } }, { brand: 'Volkswagen', year: 2005, price: 450000, owners: 3, features: { transmission: 'manual', ac: true } }, { brand: 'Toyota', year: 2017, price: 900000, owners: 1, features: { transmission: 'auto', ac: true } }, { brand: 'BMW', year: 2010, price: 750000, owners: 3, features: { transmission: 'auto', ac: true } }, { brand: 'Ford', year: 2012, price: 520000, owners: 3, features: { transmission: 'auto', ac: true } }, { brand: 'Audi', year: 2000, price: 250000, owners: 5, features: { transmission: 'manual', ac: false } }, { brand: 'Subaru', year: 2013, price: 750000, owners: 1, features: { transmission: 'auto', ac: true } } ]; console.log(cars); return { getData: function() { return cars; } } })(); var UIcontroller = (function() { return { dispalyCars: function(carsList) { var carsBlock = document.querySelector('.cars-list'); var fragment = document.createDocumentFragment(); carsList.forEach(function(item){ var newCar = document.createElement('li'); newCar.className = 'cars-list__item'; newCar.textContent = 'Марка: ' + item.brand + ', Год выпуска: ' + item.year + ', Цена: ' + item.price + ' руб. ' + 'Собственников по ПТС: ' + item.owners + '. Дополнительно ' + '(' + 'коробка: ' + item.features.transmission + ', кондиционер: ' + item.features.ac + ')'; fragment.appendChild(newCar); }); carsBlock.appendChild(fragment); }, filterData: function(carsList) { var brand = document.querySelector('.filter__brand'); var year = document.querySelector('.filter__year'); var price = document.querySelector('.filter__price'); var owners = document.querySelector('.filter__owners'); var features = document.getElementsByName('features'); var newList = carsList.filter(function(item) { switch (brand.value) { case 'toyota': return item.brand === 'Toyota'; break; case 'audi': return item.brand === 'Audi'; break; case 'ford': return item.brand === 'Ford'; break; case 'volkswagen': return item.brand === 'Volkswagen'; break; case 'bmw': return item.brand === 'BMW'; break; case 'subaru': return item.brand === 'Subaru'; break; case 'any': return item } }). filter(function(item) { switch (year.value) { case '1': return item.year <= 2000; break; case '2': return item.year <= 2010; break; case '3': return item.year >= 2010; break; case 'any': return item; } }). filter(function(item) { switch (price.value) { case 'low': return item.price <= 100000; break; case 'middle': return (item.price >= 100000 && item.price <= 500000); break; case 'high': return item.price >= 500000; break; case 'any': return item; } }). filter(function(item) { switch (owners.value) { case '1': return item.owners === 1; break; case '2': return item.owners === 2; break; case '3': return item.owners >= 3; break; case 'any': return item; } }). filter(function(item) { if (features[0].checked) { return item.features.transmission === 'auto'; } else { return item; } }). filter(function(item) { if (features[1].checked) { return item.features.ac === true; } else { return item; } }); console.log(newList); return newList }, clearList: function() { var listItem = document.querySelectorAll('.cars-list__item'); for (var i = 0; i < listItem.length; i++) { listItem[i].remove(); } }, } })(); var controller = (function(dataCtrl, UICtrl) { // 1. Получить массив с исходными данными var carsList = dataCtrl.getData(); // 2. Отрисовать исходный список авто UICtrl.dispalyCars(carsList); //Выполнить фильтрацию var filterForm = document.querySelector('.filter'); var filterFormHandler = function() { // 1. Получить данные отфильтрованного массива var filteredList = UICtrl.filterData(carsList); // 2. Очистить старый список UIcontroller.clearList(); // 3. Oтрисовать новый список UICtrl.dispalyCars(filteredList); } filterForm.addEventListener('change', filterFormHandler); })(dataController, UIcontroller); 
 .cars-list { padding: 0; margin: 0; min-height: 360px; } .cars-list__item { background-color: rgba(64, 161, 241, 0.753); box-sizing: border-box; width: 1000px; height: 30px; margin-top: 5px; margin-bottom: 5px; padding-top: 5px; padding-left: 5px; border-radius: 10px; list-style: none; } .filter { background-color: silver; width: 1000px; height: 30px; margin-top: 20px; padding-top: 5px; padding-left: 5px; border-radius: 10px; } 
 <div class="main"> <ul class="cars-list"></ul> <form action="#" class="filter" autocomplete="off"> <select name="barnd" id="brand-type" class="filter__brand"> <option value="any" selected>Любaя марка</option> <option value="toyota">Toyota</option> <option value="audi">Audi</option> <option value="ford">Ford</option> <option value="volkswagen">Volkswagen</option> <option value="bmw">BMW</option> <option value="subaru">Subaru</option> </select> <select name="year" id="cars-year" class="filter__year"> <option value="any" selected>Любой год выпуска</option> <option value="1">до 2000 года</option> <option value="2">до 2010 года</option> <option value="3">после 2010 года</option> </select> <select name="price" id="cars-price" class="filter__price"> <option value="any" selected>Любая цена</option> <option value="low">до 100000&#x20bd;</option> <option value="middle">100000 - 500000&#x20bd;</option> <option value="high">от 500000&#x20bd;</option> </select> <select name="owners" id="cars-owners" class="filter__owners"> <option value="any" selected>Любое число собственников</option> <option value="1">Один</option> <option value="2">Два</option> <option value="3">Три и более</option> </select> <input type="checkbox" name="features" value="auto" id="transmisson"> <label class="feature feature--auto" for="transmisson">Автоматическая коробка передач</label> <input type="checkbox" name="features" value="yes" id="conditioner"> <label class="feature feature--conditioner" for="conditioner">Кондиционер</label> </form> </div> 

  • do not make the return item from the filter function. Sometimes this can give unexpected results. It is better to explicitly return true or false . - Grundy
  • Note that the features for features you differ in only two parameters - what property to check and the value with which to compare. Both of these parameters can be stored, for example, in data-attributes of checkboxes and taken directly from the elements in the check, this will allow you to use the same function, which can be simply called in a loop by the elements. - Grundy