Leave dynamic code in an array filter

Asked

Viewed 77 times

1

I’m wanting to make my code more 'dynamic' so I don’t need to add a new block for each new item/category I add, it’s a study-only project. What I thought was to use the functions with paramêtros but I could not implement well

let animals = [{
    name: 'catOne',
    species: 'cat'
  },
  {
    name: 'catTwo',
    species: 'cat'
  },
  {
    name: 'dogOne',
    species: 'dog'
  },
  {
    name: 'dogTwo',
    species: 'dog'
  },
]

let catsEl = document.getElementById('cats');
let dogsEl = document.getElementById('dogs');
let result = document.getElementById('list');

let clickCount = 0;

catsEl.addEventListener('click', function() {

  clickCount++;

  function isAnimal(animal, species) {
    return animal.species === species;
  }

  let cat = animals.filter(function(animal) {
    return isAnimal(animal, 'cat');
  });

  let lis = document.createElement('li');


  for (let i = 0; i <= clickCount; i++) {
    for (let j = 0; j < i; j++) {
      result.appendChild(lis).textContent = cat[j].name;

      if (clickCount > cat.length) {
        result.appendChild(lis).textContent = "No more cats";
      }
    }


  }

});
html {
  font-family: Verdana;
}

.wrapper {
  display: flex;
}

.button {
  padding: 10px;
  width: 100%;
  border: 1px solid;
  width: 100px;
  text-align: center;
  margin: 0 20px;
}

.button:hover {
  background: #111;
  color: #fff;
}

ul#list li {
  padding: 10px;
  border: 1px solid #111;
  list-style-type: none;
  width: 10vw;
}
<div class="wrapper">
  <div class="button" id="cats">Cats</div>
  <div class="button" id="dogs">Dogs</div>
</div>

<div>
  <ul id="list"></ul>
</div>

  • I think I was not very clear excuse, but I want for example to do the same thing as the 'Cats' button on the 'dogs' button or whatever else I add, without having to duplicate all my javascript, and replace the 'Cats' in the filter with 'dogs'. , I don’t want to have to mess with the code every time I add a new "Animal" to the arraye in html

  • I understood, and <ul id="list"></ul> will be the same ? Or when clicking would have to have only the species that the user clicked?

1 answer

0


Even considering only cats, the logic you have is complex and with a mistake when you pass the amount of existing cats:

for (let i = 0; i <= clickCount; i++) {
    for (let j = 0; j < i; j++) {
      result.appendChild(lis).textContent = cat[j].name; //<--aqui

For the first for goes up to the number of clicks that may already be off the amount of cats you have. Besides, you don’t need a for to fetch a specific element from the array.

For only cats can do this way:

let animals = [{
    name: 'catOne',
    species: 'cat'
  },
  {
    name: 'catTwo',
    species: 'cat'
  },
  {
    name: 'dogOne',
    species: 'dog'
  },
  {
    name: 'dogTwo',
    species: 'dog'
  },
];

let catsEl = document.getElementById('cats');
let dogsEl = document.getElementById('dogs');
let result = document.getElementById('list');

let clickCount = 0;

catsEl.addEventListener('click', function() {
  //filter só numa linha com Arrow Functions
  let cats = animals.filter(animal => animal.species === 'cat');

  if (clickCount < cats.length){ //se ainda tem elementos para por
    let lis = document.createElement('li');
    //vai buscar o gato pela posição dada pela variavel clickCount
    result.appendChild(lis).textContent = cats[clickCount].name;
  }
  else if (clickCount == cats.length){ //se está no ultimo
    let lis = document.createElement('li');
    result.appendChild(lis).textContent = "No more cats";
  }

  clickCount++;
});
html {
  font-family: Verdana;
}

.wrapper {
  display: flex;
}

.button {
  padding: 10px;
  width: 100%;
  border: 1px solid;
  width: 100px;
  text-align: center;
  margin: 0 20px;
}

.button:hover {
  background: #111;
  color: #fff;
}

ul#list li {
  padding: 10px;
  border: 1px solid #111;
  list-style-type: none;
  width: 10vw;
}
<div class="wrapper">
  <div class="button" id="cats">Cats</div>
  <div class="button" id="dogs">Dogs</div>
</div>

<div>
  <ul id="list"></ul>
</div>

In this example the clickCount serves as the position where you fetch elements to add, referring only to cats. Note that I used Arrow Functions in the filter greatly simplifying.

Now to generalize this logic to dogs and cats the best is to create a function with the logic that is common to both and just call it in each click function. This function will need to receive the species to be added, and information regarding the clickcount because there has to be a different count for each species:

let animals = [{
    name: 'catOne',
    species: 'cat'
  },
  {
    name: 'catTwo',
    species: 'cat'
  },
  {
    name: 'dogOne',
    species: 'dog'
  },
  {
    name: 'dogTwo',
    species: 'dog'
  },
];

let catsEl = document.getElementById('cats');
let dogsEl = document.getElementById('dogs');
let result = document.getElementById('list');

let clickCounts = [0, 0]; //agora um array de contagem de clicks por especie

function addAnimal(species, speciesIndex){//adicionar um animal leva especie e clicks
  let filteredAnimals = animals.filter(animal => animal.species === species);
  let clickCount = clickCounts[speciesIndex]; //obter os clicks para esta especie

  if (clickCount < filteredAnimals.length){
    let lis = document.createElement('li');
    result.appendChild(lis).textContent = filteredAnimals[clickCount].name;
  }
  else if (clickCount == filteredAnimals.length){ 
    let lis = document.createElement('li');
    result.appendChild(lis).textContent = "No more " + species + "s";
  }

  clickCounts[speciesIndex]++; //o incremento tem de ser no array
}

catsEl.addEventListener('click', function(){ 
  addAnimal('cat',0); //click para gatos passando posição dos clicks 0
});

dogsEl.addEventListener('click', function(){ 
  addAnimal('dog',1); //click para cães passando posição dos clicks 1
});
html {
  font-family: Verdana;
}

.wrapper {
  display: flex;
}

.button {
  padding: 10px;
  width: 100%;
  border: 1px solid;
  width: 100px;
  text-align: center;
  margin: 0 20px;
}

.button:hover {
  background: #111;
  color: #fff;
}

ul#list li {
  padding: 10px;
  border: 1px solid #111;
  list-style-type: none;
  width: 10vw;
}
<div class="wrapper">
  <div class="button" id="cats">Cats</div>
  <div class="button" id="dogs">Dogs</div>
</div>

<div>
  <ul id="list"></ul>
</div>

If you want you can also modify the place where each species is added in html. In this case you would also have to modify the animal addition function to receive the html element to place the result.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.