Вычисление нескольких итогов из цикла v-for - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть уникальная ситуация, когда у меня есть цикл пользователей v-for (персонал), и внутри него у меня есть другой цикл v-for, проверяющий отпуск, накопленный пользователем.

проще говоря

v-for get user
    //Print users name
    v-for get any leave associated with this user
          //Print that days Annual Leave
          //Print that days Sick Leave
    v-end
    //Print total Annual Leave
    //Print total Sick Leave
v-end

Содержимое базы данных об отпуске имеет следующие значения

Тип: (Отпуск по болезни, Ежегодный отпуск, Тяжелая утрата и т. Д.) Часы: целое число

Так что, по сути, он скажет

Thomas               Annual        Sick
------------------------------------------
Annual Leave         2 hours       0 Hours
Sick Leave           0 Hours       3 Hours
Annual Leave         4 Hours       0 Hours
-------------------------------------------
Total                6 Hours       3 Hours

John                 Annual        Sick
------------------------------------------
Annual Leave         2 hours       0 Hours
Annual Leave         2 Hours       0 Hours
-------------------------------------------
Total                4 Hours       0 Hours

Теперь о коде и о том, что у меня есть:

<div v-for="user_list in user_list_filtered()">
   <div class="user_heading"><h2>{{ user_list.first_name }}</h2></div>
   <div class="report_content" v-for="userleave in user_leave_filtered(user_list['.key'])">
      <div class="leave_type_content">
         {{ userleave.type }}
      </div>
      <div class="days_taken_content">
         //Get Leave
      </div>
      <div class="lsl_content">
         //Get Sick Leave
      </div>
   </div>
   <div class="leave_content">
      <div class="total_leave_title">
         Total Leave Taken
      </div>
      <div class="total_hours">
         // Print Total Leave
      </div>
      <div class="total_hours">
         //Print Total Sick Leave
      </div>
   </div>
</div>

Так что, если он имеет тип Sick Leave, добавьте его ввторой столбец и установите для первого столбца значение 0 или, если! == Отпуск по болезни установите для первого столбца значение, а для второго столбца - 0. Затем добавьте каждую сторону вверх и напечатайте ниже.

Я пробовал некоторые вещи как функциино я получаю бесконечные циклы, поэтому я застрял, потому что большинство постов не так сложны, как то, что я пытаюсь достичь.

Спасибо за помощь

Редактировать: Дополнительные функции

user_leave_filtered(userPassed) {
  var self = this
  return this.userLeave.filter(function (i) {
    if (i.users_id === userPassed &&
      ((i.start_time >= self.getUnix(self.firstDate) && i.start_time <= self.getUnix(self.lastDate)) ||
        (self.firstDate === null || self.firstDate === '' || self.lastDate === null || self.lastDate === ''))) {
      return true
    } else {
      return false
    }
  })
},
user_list_filtered() {
  var self = this

  return this.userList.filter(function (i) {

    var passed = false

    if (self.userToShow === i['.key'] || self.userToShow === 'All') {
      // Track whether to filter out this leave or not
      self.userLeave.forEach(function (element) {
        if (element.users_id === i['.key']) {
          passed = true
        } else {}
      })
    }

    return passed
  })
},

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

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

computed: {
  usersWithLeave () {
    const unixFirstDate = this.firstDate && this.getUnix(this.firstDate)
    const unixLastDate = this.lastDate && this.getUnix(this.lastDate)
    // first map the leave entries by user for quick access
    const leaveByUser = this.userLeave.reduce((map, element) => {
      // Filter out by dates
      if (
          (!unixFirstDate || element.start_time >= unixFirstDate) &&
          (!unixLastDate || element.start_time <= unixLastDate)
      ) {
        const elements = map.get(element.users_id) || []
        elements.push(element)
        map.set(element.users_id, elements)  
      }
      return map
    }, new Map())

    // now construct a filtered array of users then map to one with leave attached
    return this.userList
        .filter(({'.key': id}) => [id, 'All'].includes(this.userToShow) && leaveByUser.has(id))
        .map(({'.key': id, first_name}) => {
          const leave = leaveByUser.get(id)
          return {
            first_name,
            leave, // an array of all leave elements
            totals: leave.reduce((totals, element) => {
              totals[element.type === 'Sick Leave' ? 'sick' : 'annual'] += element.Hours
              return totals
            }, { sick: 0, annual: 0 })
          }
        })
  }
}

Ого, это было больше работы, чем ожидалось.Это создаст массив объектов, которые будут выглядеть примерно так:

{
  first_name: 'Thomas',
  leave: [
    { type: 'Annual Leave', Hours: 2 },
    { type: 'Sick Leave', Hours: 3 },
    { type: 'Annual Leave', Hours: 4 }
  ],
  totals: {
    sick: 3,
    annual: 6
  }
}

Теперь вы можете легко использовать это в своем шаблоне

<div v-for="user in usersWithLeave">
  <div class="user_heading"><h2>{{ user.first_name }}</h2></div>
  <div class="report_content" v-for="userleave in user.leave">
      <div class="leave_type_content">
        {{ userleave.type }}
      </div>
      <div class="days_taken_content">
        {{ userleave.type !== 'Sick Leave' && userleave.Hours || 0 }}
      </div>
      <div class="lsl_content">
      {{ userleave.type === 'Sick Leave' && userleave.Hours || 0 }}
      </div>
  </div>
  <div class="leave_content">
      <div class="total_leave_title">
        Total Leave Taken
      </div>
      <div class="total_hours">
        {{ userleave.totals.annual }}
      </div>
      <div class="total_hours">
        {{ userleave.totals.sick }}
      </div>
  </div>
</div>
0 голосов
/ 19 сентября 2018

Первое правило: не вызывайте функции в своем HTML.Вместо этого используйте вычисленные свойства .

Вы можете получить отфильтрованный список пользователей и map, чтобы представить данные, необходимые для пользователя.

В любом случае, я рекомендую вам обработать отображение «пользовательских листьев» в серверной части и привести данные настолько близко, насколько вы будете использовать их в клиенте.

Это пример того, как я бы обратилсяваш случай (обратите внимание, я не использую ту же структуру объекта, которую вы, вероятно, используете, поскольку вы не предоставили полный код в своем вопросе)

new Vue({
  el: "#app",
  data: {
    userList: [
      { id: 1, firstName: "Jon Doe" },
      { id: 2, firstName: "Jane Doe" }
    ],
    userLeave: [
      { userId: 1, type: "anual", hours: 2 },
      { userId: 1, type: "sick", hours: 3 },
      { userId: 1, type: "anual", hours: 4 },
      { userId: 2, type: "anual", hours: 2 },
      { userId: 2, type: "sick", hours: 3 },
      { userId: 2, type: "anual", hours: 4 }
    ]
  },
  computed: {
    usersById () {
      if (!this.userList.length) return null;
      // create a list of users by id and save a few iterations
      return this.userList.reduce((list, user) => {
        list[user.id] = user;
        return list  
      }, {})
    },
    filteredUsers () {
      if (!this.userLeave.length) return [];
      const users = {}
      this.userLeave.forEach(leave => {
        const user = this.usersById[leave.userId]
        if (user) {
          if (leave.type === "sick") {
            user.totalSick = typeof user.totalSick === "number"
              ? leave.hours + user.totalSick
              : leave.hours;
          } else {
            user.totalAnual = typeof user.totalAnual === "number"
              ? leave.hours + user.totalAnual
              : leave.hours;
          }
          if (user.leaves === undefined) user.leaves = []
          user.leaves.push(leave)
          users[user.id] = user
        }
      })
      return users
    }
  }
})
.leave_type_content,
.days_taken_content,
.lsl_content,
.total_leave_title,
.total_hours,
.total_hours {
  display: inline-block
}
<script src="https://unpkg.com/vue@2.5.17/dist/vue.min.js"></script>
<div id="app">
  <div v-for="user in filteredUsers"> <!-- NOTICE THE COMPUTED PROPERTY -->
   <div class="user_heading"><h2>{{ user.firstName }}</h2></div>
   <div class="report_content" v-for="userleave in user.leaves">
      <div class="leave_type_content">
         {{ userleave.type }}
      </div>
      <div class="days_taken_content">
         {{ userleave.type === "anual" && userleave.hours || 0 }} hours
      </div>
      <div class="lsl_content">
         {{ userleave.type === "sick" && userleave.hours || 0 }} hours
      </div>
   </div>
   <div class="leave_content">
      <div class="total_leave_title">
         Total Leave Taken
      </div>
      <div class="total_hours">
         {{ user.totalAnual }}
      </div>
      <div class="total_hours">
         {{ user.totalSick }}
      </div>
   </div>
</div>
</div>
...