Vue.js - создание заголовков букв для отсортированного по алфавиту списка - PullRequest
0 голосов
/ 11 января 2019

Я перебираю объект JSON следующего типа:

"entries": [{
    "first_name": "Brigitte",
    "last_name": "Bardot",
    "country": "Paris, France",
    "profession": "Actress"
  },
  {
    "first_name": "Apollo",
    "last_name": "AA",
    "country": "Witten, Germany",
    "profession": "Writer"
  }]

Используя v-for и lodash, у меня есть список этих записей в алфавитном порядке:

<div v-for="user in orderedUsers" :key='user' class="user">
<p>{{ user.first_name }} {{ user.last_name }} ({{ user.country }}), {{ user.profession }}</p> 
</div>

Я хотел бы создать заголовок, содержащий первую букву фамилии, чтобы сгруппировать записи в алфавитном порядке:

A

Apollo

B

Бардо

и т.д ..

Для сортировки записей используется следующая функция:

computed: {
      orderedUsers: function () {
        return orderBy(this.text[0].entries, 'last_name')
      }
    }

Есть какие-нибудь идеи о простом и эффективном способе достижения этого?

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Тем временем было предложено следующее решение, но я думаю, что ответ Ори Дори проще.

let users = orderBy(this.text[0].entries, 'last_name');

    const map1 = users.map(x => x.last_name.substring(0,1));

    const letters = map1.filter(function(item, index){
  return map1.indexOf(item) >= index;
});

const groups = {};

// create groups containers from names
letters.forEach(k => {
  groups[k] = []
});

 users.forEach(k => {
  const user = k.last_name.substring(0,1)
  groups[user].push(k)
})

  return groups
0 голосов
/ 11 января 2019

Упорядочить записи по last_name и сгруппировать по 1-й букве каждого пользователя. Переберите элементы с помощью flatMap и добавьте ключ (фамилию).

В vue используйте v-if (элемент является строкой) и v-else, чтобы принять решение о визуализации элемента или заголовка.

const { flow, orderBy, groupBy, flatMap, get } = _
const entries = [{"first_name":"Brigitte","last_name":"Bardot","country":"Paris, France","profession":"Actress"},{"first_name":"Apollo","last_name":"AA","country":"Witten, Germany","profession":"Writer"}]
  
const groupItems = flow([
  arr => orderBy(arr, 'last_name'),
  arr => groupBy(arr, o => get(o, 'last_name[0]', '').toUpperCase()),
  groups => flatMap(groups, (v, k) => [
    k,
    ...v
  ])
])

new Vue({
  el: '#app',
  data: { orderedUsers: groupItems(entries) }
})
/** hide the annoying vue production messages **/
.as-console-wrapper {
  display: none !important;
}
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

<div id="app">
  <div v-for="item in orderedUsers">
    <h2 v-if="typeof item === 'string'">
      {{ item }}
    </h2>
      <p v-else>{{ item.first_name }} {{ item.last_name }} ({{ item.country }}), {{ item.profession }}</p> 
  </div>
</div>
...