使用Vuejs传递对象的格式化日期输入框

问题描述 投票:0回答:1

我有一个使用Vuejs动态生成的表。它在呈现为readOnly的单元格中具有输入元素。每个元素都有一个“编辑”按钮,单击后将变为“保存”,并启用该行的输入元素进行编辑。单击保存时,我想捕获输入的新值和先前的值。我将日期字段从原始格式设置为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。感谢您可以提供的任何帮助。

javascript vue.js vuejs2
1个回答
0
投票

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

v-model需要分配一个变量,以便输入可以更新其值。现在,您正在使用[[0]无法工作的v-model="formatDate(program)",因为传递函数的静态结果无法进行反应。有几种方法可以完成此操作。这是

只是完成它

的示例。当然还有改进和替代实现的空间...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 } },

更新

如上所述,使用函数格式化模板中的值不是一个好主意。相反,请在使用前重新格式化数据(请参见地图功能)一旦采用正确的格式,就可以使用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>
© www.soinside.com 2019 - 2024. All rights reserved.