Synchro
Synchro

Reputation: 1269

Vue js how to Choice item in array

enter image description here

I have an array of alphabets, I want to make it so that the user can select one of these letters, then when you click on the button named "All" with an alert, the name of the selected letter is displayed, this construction looks like this

You can also look at this project in codesandbox

<template>
  <div>
    <div class="alphabet-container">
      <div
        class="alphabet-row"
        v-for="i in Math.ceil(alphabet.length / 6)"
        :key="i.id"
      >
        <span
          class="AlphabetLetters"
          :class="item"
          v-on:click="show(item)"
          v-for="(item, index) in alphabet.slice((i - 1) * 6, i * 6)"
          :key="index"
        >
          {{ item }} <br v-if="(index + 1) % 6 == 0" />
        </span>
      </div>
      <div class="alphabet-btn">
        <button>All</button>
      </div>
    </div>
  </div>
</template>

<script>
import _ from "lodash";

export default {
  data() {
    return {
      alphabet: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 
      'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
    };
  },

  methods: {
    computed: {
      productChunks() {
        return _.chunk(Object.values(this.products), 4);
      },
    },
    show(item) {
      alert(item);
    },
  },
};
</script>

<style scoped>
   .B {
     border: 1px solid #74c8c5;
     border-radius: 5px;
   }
</style>

Upvotes: 0

Views: 111

Answers (2)

painotpi
painotpi

Reputation: 6996

You can have a state like selectedAlphabet as @Melvynx suggested. And you can move your click event from the alphabet to the button.

<template>
  <div>
    <div class="alphabet-container">
      <div
        class="alphabet-row"
        v-for="i in Math.ceil(alphabet.length / 6)"
        :key="i.id"
      >
        <span
          class="AlphabetLetters"
          :class="{ 'blue-border': item === selectedAlphabet }"
          v-on:click="selectedAlphabet = item"
          v-for="(item, index) in alphabet.slice((i - 1) * 6, i * 6)"
          :key="index"
        >
          {{ item }} <br v-if="(index + 1) % 6 == 0" />
        </span>
      </div>
      <div class="alphabet-btn">
        <button :click="show()">All</button>
      </div>
    </div>
  </div>
</template>

<script>
import _ from "lodash";

export default {
  data() {
    return {
      selectedAlphabet: 'A',
      alphabet: [
        "A",
        "B",
        "C",
        "D",
        "E",
        "F",
        "G",
        "H",
        "I",
        "J",
        "K",
        "L",
        "M",
        "N",
        "O",
        "P",
        "Q",
        "R",
        "S",
        "T",
        "U",
        "V",
        "W",
        "X",
        "Y",
        "Z",
      ],
    };
  },

  methods: {
    computed: {
      productChunks() {
        return _.chunk(Object.values(this.products), 4);
      },
    },
    show() {
      alert(this.selectedAlphabet);
    },
  },
};
</script>

<style scoped>
.alphabet-container {
  width: 200px;
  margin: auto;
  max-width: 100%;
}

.alphabet-row {
  display: flex;
  justify-content: space-between;
}

.AlphabetLetters {
  font-family: "Second-Montserrat-Bold";
  cursor: pointer;
  font-style: normal;
  font-weight: bold;
  font-size: 12px;
  line-height: 14px;
  padding: 10px;
}

.Z {
  display: flex;
  justify-content: flex-start;
  width: 100%;
}

.blue-border {
  border: 1px solid #74c8c5;
  border-radius: 5px;
}

.alphabet-btn {
  position: relative;
}

.alphabet-btn button {
  position: absolute;
  cursor: pointer;
  right: 0;
  bottom: 0;
  background: #74C8C5;
  padding: 8px 40px;
  border: none;
  outline: none;
  border-radius: 5px;
  color: #ffffff;
}
</style>

Side note:

I think you can do away with the loop on the parent div (alphabet-row) and also remove the slice methods in the code, it should just work fine without it. If you're using it to control how many alphabets appear on a row, you can do that with only css.

Edit:

You've also put computed inside methods which is incorrect.

Upvotes: 1

Melvynx
Melvynx

Reputation: 1175

You can add a state like selectedAlphabet which contains the selected letter. Your function show will set selectedAlphabet to the item.

In your HTML, you juste can add a conditionnal class that add a border if the selectedAplhabet === item :

       <span
          class="AlphabetLetters"
          :class="item"
          v-bind:class="{ 'blue-border': item === selectedAlphabet }" <--
          v-on:click="show(item)"
          v-for="(item, index) in alphabet.slice((i - 1) * 6, i * 6)"
          :key="index"
        >

Upvotes: 1

Related Questions