我有一个使用 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> <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/