javascript - 使用 Vuejs 传入对象来格式化日期输入框

标签 javascript vue.js vuejs2

我有一个使用 Vuejs 动态生成的表。它在单元格中具有呈现为只读的输入元素。每个元素都有一个“编辑”按钮,单击该按钮时,它会更改为“保存”并启用该行的输入元素进行编辑。单击“保存”时,我想捕获输入的新值和以前的值。我将日期字段的格式设置为 mm/dd/yy(原始格式为 2019-10-10T07:00:00Z) 我能够成功格式化日期使用 momentjs 但它似乎不坚持。输入的值与我提醒时不同。对我做错了什么有什么想法吗?我是否需要重构我的代码以允许我执行此操作,因为必须对每个字段执行此操作,以便访问新值和以前的值。

<div id="app">
<table border=1 width=100%>
  <tr>
    <td>EDIT</td>
    <td v-for="editableKey in editableKeys" :key="editableKey" class="label">{{ editableKey }}</td>
  </tr>
  <tr v-for="(program, index) in programs">
    <td><button v-if="program.isReadOnly" v-on:click="editItem(program)">edit</button>&nbsp;<button @click="saveItem(program)" v-else>save</button></td>    
    <td><input type="text" v-bind:data-id="program.id" :readonly="program.isReadOnly" v-model="formatDate(program)"></td>  
    <td><input type="text" v-bind:data-id="program.id" :readonly="program.isReadOnly" v-model="program.company"></td>
    <td><input type="text" v-bind:data-id="program.id" :readonly="program.isReadOnly" v-model="program.funding"></td>
    <td><input type="text" v-bind:data-id="program.id" :readonly="program.isReadOnly" v-model="program.funded"></td>
    <td><select :class="bgColor(program)" type="text" v-bind:data-id="program.id" :disabled="program.isReadOnly" v-model="program.Recruit">
            <option>Internal</option>
            <option>Recruiting</option>
        </select>
      <!--<input  :class="bgColor(program)" type="text" v-bind:data-id="program.id" :readonly="program.isReadOnly" v-model="program.Recruit">--></td>
    <td><input type="text" v-on:change="" v-bind:data-id="program.id" :readonly="program.isReadOnly" v-model="program.program"></td>    
  </tr>
</table>

</div>



new Vue({
  el:"#app",
  data: () => ({
    programs: [],
    editableKeys: ['date', 'company', 'funding', 'funded', 'recruit', 'program'],
  }),
  created () {
    this.getPrograms();
  },
  methods: {
    getPrograms() {
     axios.get("https://my-json-server.typicode.com/isogunro/jsondb/Programs").then(response => {
       this.programs = response.data.map(program => ({
           ...program,
           isReadOnly: true
       }));
      }).catch(error => {
       console.log(error);
      });
    },
    editItem (program) {
      program.isReadOnly = false
    },
    saveItem (program) {
      program.isReadOnly = true
      console.log(program)
      alert("New Value: "+program.Date)
      alert("Previous Value: "+program.Date)
    },
    bgColor (program) {
      return program.funded === program.funding ? 'yellow' : 'white'
    },
    formatDate(program){
      var formatL = moment.localeData().longDateFormat('L');
      var format2digitYear = formatL.replace(/YYYY/g,'YY');
      return moment(program.Date).format(format2digitYear);
    },
    updateField(program){
      console.log(program)
      alert(program)
    }
  }
})

这是一个pen为了清楚起见。 感谢您提供的任何帮助。

最佳答案

如果您希望它的行为方式使输入中的数据与显示的数据不同,您必须将输入与数据解耦。

v-model 需要分配一个变量,以便输入可以更新其值。现在您正在使用 v-model="formatDate(program)",它无法工作,因为传递函数的静态结果不能是 react 性的。

有多种方法可以实现此目的。这是一个刚刚完成的示例。当然还有改进和替代实现的空间......

v-model 替换为 value 和事件监听器

这定义了值的来源;生成格式化日期的函数。 (请注意,在模板中使用函数进行渲染并不是一个好的做法。最好只执行一次并使用缓存的值,这样就不必重新计算该值)

<input
  type="text"
  v-bind:data-id="program.id"
  :readonly="program.isReadOnly"
  :value="formatDate(program)"
  @input="updateDate($event, program)"
>

更新方法

    editItem (program) {
      program.isReadOnly = false
      program.tempDate = null; // added tempDate to be set to null initially
    },
    saveItem (program) {
      program.isReadOnly = true
      if(program.tempDate !== null) {
        // if tempDate is set, update Date
        program.Date = program.tempDate;
        // and clear tempDate
        program.tempDate = null;
      }
      console.log({...program})
    },
    // new method to convert value of the input from string to Date (if date passed is valid)
    updateDate(e, program ) {
      if(new Date(e.target.value).toString() !== 'Invalid Date'){
        program.tempDate = new Date(e.target.value)
      } else {
        program.tempDate = null
      }
    },

更新

如上所述,使用函数来格式化模板中的值并不是一个好主意。相反,请在使用数据之前重新格式化数据(请参阅 map 功能) 一旦格式正确,您就可以使用v-model,只是请注意,此示例不会检查日期格式的正确性。

function toDDMMYY(date) {
  const [y, m, d] = (new Date(date)).toISOString().slice(0, 10).split('-')
  return `${d}/${m}/${y%100}`
}
new Vue({
  el: "#app",
  data() {
    return {
      test: "hello",
      programs: "",
      hide: true,
      editable: [],
    }
  },
  created: function() {
    this.getPrograms();
  },
  methods: {
    getPrograms: function() {
      axios.get("https://my-json-server.typicode.com/isogunro/jsondb/Programs").then((response) => {
          this.programs = response.data.map(row => ({
            ...row,
            dateFormatted: toDDMMYY(row.Date),
            editable: false
          }));
        })
        .catch(function(error) {
          console.log(error);
        });
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>

<div id="app">
  <table border=1 width=100%>
    <tr>
      <td width=10px>EDIT</td>
      <td>Date</td>
      <td>Program</td>
      <td>Company</td>
      <td>Funding</td>
      <td>Funded</td>
      <td>Recruit</td>
    </tr>
    <tr v-for="program in programs">
      <td>
        <button v-if="program.editable == false" @click="program.editable = true">edit</button>
        <button v-else @click="program.editable = false">save</button>
      </td>
      <td><input type="text" v-bind:data-id="program.id" :readonly="!program.editable" v-model="program.dateFormatted"></td>
      <td><input type="text" v-bind:data-id="program.id" :readonly="!program.editable" v-model="program.program"></td>
      <td><input type="text" v-bind:data-id="program.id" :readonly="!program.editable" v-model="program.company"></td>
      <td><input type="text" v-bind:data-id="program.id" :readonly="!program.editable" v-model="program.funding"></td>
      <td><input type="text" v-bind:data-id="program.id" :readonly="!program.editable" v-model="program.funded"></td>
      <td><input type="text" v-bind:data-id="program.id" :readonly="!program.editable" v-model="program.Recruit"></td>
    </tr>
  </table>

</div>

关于javascript - 使用 Vuejs 传入对象来格式化日期输入框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58611817/

相关文章:

javascript - 使用 jQuery 读取 CSV 以传递给 Google Visualization API

javascript - 我可以让自动布局 js 在 canvas/pixijs 上工作吗

javascript - 如何访问另一个子组件中的插槽内容

vue.js - 为什么 Vuex-persist 不在 localStorage 中存储任何东西?

javascript - 使用 Vue.js 的可滚动表格

vuejs2 - Vue 组件数据未从 Prop 更新

javascript - 如何在 Vue 3 中以编程方式创建组件实例?

vue.js - prop 改变时新的 vue 组件实例

javascript - 如何清除.map回调函数中放置的间隔

javascript - 使用 bootstrap-modal 作为 Backbone.js View