如何创建时间表并将每个输入值绑定到相应的日期?

时间:2019-01-30 16:41:57

标签: javascript vue.js

我希望创建一个时间表网格。基本上,一个网格可以显示当前星期和您正在从事的项目,例如:https://jsfiddle.net/ho9a8neq/ 如何设置v模型,以便可以将具有相应日期的值正确发送到数据库? 像

[
  {date: "jan-1": 8, project: 1},
  {date: "jan-2": 10, project: 1},
  {date: "jan-3": 10, project: 2}
]

1 个答案:

答案 0 :(得分:3)

为了能够在时间轴上收集不同项目的数据并跟踪每个项目的日期,我提出的解决方案包括以下数据结构:

day = ''
week = [day, day, day]
project = [week, week, ...]
  

为简单起见,它限制了以后增加几周的时间。可以对此进行更改,但是它将需要更多的模型复杂性,而且我认为这不会有助于理解如何将数据绑定到模型。

对于每周,必须有一个保留每天数据的模型,这是通过创建一个空字符串数组来完成的:

week: ['','','','','','','']

每个项目可以包含几个星期:

data: [week, week, week]

用户创建新项目时,必须考虑当前星期复制项目模型:

_.cloneDeep(project(this.weekNum, this.rows.length))

现在,有了数据结构,将视图绑定到它:

<input type="text" style="width: 35px;" v-model="row.data[weekNum][i]">

请参阅摘要以了解所有内容如何联系在一起:

const weekData = () => new Array(7).fill('');

const project = (weekNum, id) => ({
  project: "first",
  id,
  data: Array(weekNum + 1).fill([]).map(weekData)
});

new Vue({
  el: "#app",
  data: {
    weekNum: 0,
    rows: [_.cloneDeep(project(0, 0))]
  },
  methods: {
    addProject() {
      window.pp = _.cloneDeep(
          project(this.weekNum, this.rows.length)
        )
      this.rows.push(
        window.pp
      );
    },
    deleteRow(key) {
      this.rows.splice(key, 1);
    },
    nextWeek() {
      this.weekNum++;
      this.rows.forEach(_project => {
        if (!_project.data[this.weekNum]) {
          _project.data.push(weekData());
        }
      });
    },
    prevWeek() {
      this.weekNum--;
      this.rows.forEach(row => {
        if (!row.data[this.weekNum]) {
          row.data.unshift(weekData());
        }
      });
    },
    dates(dateFormat, weekNumber) {
      let startOfWeek = moment().startOf('week').add(weekNumber, "week");
      const endOfWeek = moment().endOf('week').add(weekNumber, "week");
      const days = [];
      while (startOfWeek <= endOfWeek) {
        days.push(startOfWeek.format(dateFormat))
        startOfWeek = startOfWeek.clone().add(1, 'd');
      }
      return days
    },
    log() {
      const output = _.reduce(this.rows, (result, row) => {
        const project = {
          project: row.id
        };
        const startWeek = moment().startOf('week');
        const weekDays = [];
        row.data.forEach((week, weekIdx) => {
          week.forEach((data, dataIdx) => {
            if (data === '') return;
            weekDays.push({
              data,
              project: row.id,
              day: startWeek.clone().add(weekIdx, 'week').add(dataIdx, 'd').format('MMM D')
            });
          });
        });
        return [...result, ...weekDays];
      }, []);
      console.log(output)
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.min.js"></script>

<div id="app">
  <!-- for the sake of simplicity limit the date to future weeks -->
  <button @click="prevWeek" :disabled="weekNum < 1">Previous week</button>
  <button @click="nextWeek">Next week</button>
  <button @click="addProject">Add project</button>
  <table>
    <tr>
      <th>Project</th>
      <th v-for="(day, i) in dates('MMM D', weekNum)" :key="i">{{day}}</th>
    </tr>
    <tbody>
      <tr v-for="(row, key) in rows" :key="key">
        <td>Project {{key}}</td>
        <td v-for="(n,i) in dates('YYYY-MM-DD', weekNum)" :key="`${row.id}-${i}`">
          <input type="text" style="width: 35px;" v-model="row.data[weekNum][i]">
        </td>
        <td><button @click="deleteRow(key)">x</button></td>
      </tr>
    </tbody>
  </table>
  <button @click="log()">log</button>
</div>