点击编辑按钮,前端table表格行内指定td可修改。(table是动态生成的)

本文介绍了一个基于Ajax的表格编辑功能实现方法,通过JavaScript操作DOM,实现了表格内容的动态加载及行内元素的编辑、保存与取消功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.先上最后效果图:



2.代码跟上,重点在 2):

1)
//服务列表页面动态加载服务
      function ready() {
   var url = base_path+"console/cfg/getBaseLayers/"+configId;
   $.ajax({
      url:url,
      type:"get",
      dataType:"json",
      success:function (result) {
         //生成之前先清空tr,防止AJAX异步加载重复生成
         $("#lot tr").remove();

         var length = result.length;
         for (var i=0;i<length;i++){
            var name = result[i].name; //服务名称
            var alias = result[i].alias;//服务别名
            var type = result[i].type;//服务类型
            var year = result[i].year;//年份
            var url = result[i].url;//服务地址
            var visible = result[i].visible;//是否可见
            var id =  result[i].id;//id
                      serviceIdArray[i] = id;//此处将id塞给serviceIdArray,用于判断是否添加。
            var str = "";
            if (visible==true){
               //生成tr
               str += '<tr id = "';
               str += id;
               str += '"';
               str += ' class="lot_box"> <td>';
               str += i+1;
               str += '</td> <td>';
               str += name;
               str += '</td> <td>';
               str += alias;
               str += '</td> <td>';
               str += type;
               str += '</td> <td>';
               str += year;
               str += '</td> <td>';
               str += url;
               str += '</td> <td>';
               str += '<input id="';
               str += id;
               str += '"';
               str += 'type="checkbox" checked="true" onchange="modifyService(this.id);"/>';
               str += '</td> <td> <input id="';
               str += id;
               str += '"';
               str += 'type="button" value="编辑" onclick="editTd(this.id)"/>';
               str += '</td> <td>';
               str += '<button class="rosy" id="';
               str += id;
               str += '"';
               str += ' onclick="deleteService(this.id);">';
               str += '<img src="static/img/del14.png"></button>';
               str += '</td> </tr>';
            }else {
               //生成tr
               str += '<tr id = "';
               str += id;
               str += '"';
               str += ' class="lot_box"> <td>';
               str += i+1;
               str += '</td> <td>';
               str += name;
               str += '</td> <td>';
               str += alias;
               str += '</td> <td>';
               str += type;
               str += '</td> <td>';
               str += year;
               str += '</td> <td>';
               str += url;
               str += '</td> <td>';
               str += '<input id="';
               str += id;
               str += '"';
               str += 'type="checkbox" onchange="modifyService(this.id);"/>';
               str += '</td> <td> <input id="';
               str += id;
               str += '"';
               str += 'type="button" value="编辑" onclick="editTd(this.id)"/>';
               str += '</td> <td>';
               str += '<button class="rosy" id="';
               str += id;
               str += '"';
               str += ' onclick="deleteService(this.id);">';
               str += '<img src="static/img/del14.png"></button>';
               str += '</td> </tr>';
            }
            var $tr = $(str);
            $("#lot").append($tr);
         }
      }
   });
}


2)

//修改table行内元素(td)
function editTd(id) {
   //选中编辑按钮的时候,把这行指定的几个td变成文本框
   var b = $("input[type='button'][id='"+id+"']").parent(); //td
   var a = b.siblings(); //td的兄弟节点
   if(a[1].children.length===0){
      a[1].innerHTML="<input type='text' value='"+a[1].innerText+"'/>";
   }
   if(a[2].children.length===0){
      a[2].innerHTML="<input type='text' value='"+a[2].innerText+"'/>";
   }
   if(a[3].children.length===0){
      a[3].innerHTML="<input type='text' value='"+a[3].innerText+"'/>";
   }
   //将编辑改成 保存和取消两个按钮
   b[0].innerHTML="<input id='"+id+"' type='button' onclick='saveEditTd(this.id);' value='保存'/><input type='button' onclick='resertEditTd();' value='取消'/>";
   
   //以下注掉的都是在网上找的参考。
   /*alert(a[0].getText());
   var $this = $(this).index();
   alert($this);*/

   /*$('input[type="button"]').on('click', function(){
      var $this = $(this).parent().parent();//tr
      ready();
   });*/

   /*var $ = function(node) {
      return typeof node == "string" ? document.getElementById(node) : node;
   }
   var $1 = function(node, parent){
      var nd = document.createElement(node);
      if(parent) parent.appendChild(nd);
      return nd;
   }
   /!** 绑定事件流 *!/
   var bind = function(obj, eventName, funcionName){
      if(obj.addEventListener){
         obj.addEventListener(eventName, funcionName,false);
      }else if(obj.attachEvent) {
         obj.attachEvent("on" + eventName, funcionName);
      }else{
         obj["on" + eventName] = funcionName;
      }
   };

   var fulltable = function(tbody, data){
      var pd = data.data;
      var column = data.column;
      for(var i=0, len=data.rows; i<len; i++){
         var tr = $1("tr", tbody);
         var cd = pd[i];
         for(var j=0,jlen=column.length; j<jlen; j++){
            var td = $1("td", tr);
            td.innerHTML = cd[column[j]];//innerText不兼容火狐,可以自己写innerTexttextContent的兼容,这里就直接用innerHTML
         }
      }
   }
   var littlehow_edit_table = function(tbody, ev){
      this.tbody = $(tbody);
      this.event = ev ? ev : "click";//默认为单机事件
      this.init = function(data) {//data可以是undefined
         if(data) {
            fulltable(this.tbody, data);
         }
         //调用可编辑
         this.edit();
      }
      this.edit = function(){
         var tds = this.tbody.getElementsByTagName("td");
         for(var i=0,len=tds.length; i<len; i++){
            bind(tds[i], this.event, this.click);
         }
      }
      this.click = function(){
         //alert(this.children.length);
         if(this.children.length > 0) return;
         var v = this.innerHTML;
         this.innerHTML = "";
         var input = $1("input", this);
         input.type = "text";
         input.value = v;
         input.focus();//光标聚集
         bind(input, "blur", blur);
      }
      var blur = function(){
         var v = this.value;
         this.parentNode.innerHTML = v;
      }
   }
   window.$$ = function(id, ev){
      return new littlehow_edit_table(id, ev);
   };*/

   /*$('.editable').handleTable({
      "handleFirst" : true,
      "cancel" : " <span class='glyphicon glyphicon-remove'></span> ",
      "edit" : " <span class='glyphicon glyphicon-edit'></span> ",
      "add" : " <span class='glyphicon glyphicon-plus'></span> ",
      "save" : " <span class='glyphicon glyphicon-saved'></span> ",
      "confirm" : " <span class='glyphicon glyphicon-ok'></span> ",
      "operatePos" : -1,
      "editableCols" : [2,3,4],
      "order": ["add","edit"],
      "saveCallback" : function(data, isSuccess) { //这里可以写ajax内容,用于保存编辑后的内容
         //data: 返回的数据
         //isSucess: 方法,用于保存数据成功后,将可编辑状态变为不可编辑状态
         var flag = true; //ajax请求成功(保存数据成功),才回调isSuccess函数(修改保存状态为编辑状态)
         if(flag) {
            isSuccess();
            alert(data + " 保存成功");
         } else {
            alert(data + " 保存失败");
         }

         return true;
      },
      "addCallback" : function(data,isSuccess) {
         var flag = true;
         if(flag) {
            isSuccess();
            alert(data + " 增加成功");
         } else {
            alert(data + " 增加失败");
         }
      },
      "delCallback" : function(isSuccess) {
         var flag = true;
         if(flag) {
            isSuccess();
            alert("删除成功");
         } else {
            alert("删除失败");
         }
      }
   });*/

   /*//dom创建文本框
   var input = document.createElement("input");
   input.type="text" ;
   //得到当前的单元格
   var currentCell ;
   function editCell(event) {
      if(event==null) {
         currentCell=window.event.srcElement;
      }
      else {
         currentCell=event.target;
      }
      //根据Dimmacro 的建议修定下面的bug 非常感谢
      if(currentCell.tagName=="TD"){
         //用单元格的值来填充文本框的值
         input.value=currentCell.innerHTML;
         //当文本框丢失焦点时调用last
         input.onblur=last;
         input.ondblclick=last;
         currentCell.innerHTML="";
         //把文本框加到当前单元格上.
         currentCell.appendChild(input);
         //根据liu_binq63 的建议修定下面的bug 非常感谢
         input.focus();
      }
   }
   function last() {
      //充文本框的值给当前单元格
      currentCell.innerHTML = input.value;
   }
   //最后为表格绑定处理方法.
   document.getElementById("table").ondblclick=editCell;*/

   /*var ttr = $(this).val()=="编辑"?"确定":"编辑";

   $(this).val(ttr);   // 按钮被点击后,在编辑确定之间切换

   $(this).parent().siblings("td").each(function() {  // 获取当前行的其他单元格

      var obj_text = $(this).find("input:text");    // 判断单元格下是否有文本框

      if(!obj_text.length)   // 如果没有文本框,则添加文本框使之可以编辑

         $(this).html("<input type='text' value='"+$(this).text()+"'>");

      else   // 如果已经存在文本框,则将其显示为文本框修改的值

         $(this).html(obj_text.val());

   });*/

   /*$('input[type="button"]').on('click', function(){
      var $this = $(this);
      var $td_arr = $this.parent().html('保存').prevAll('td');
      $.each($td_arr, function(){
         var $td = $(this);
         $td.html('<input type="text" value="'+$td.html()+'">');
      });
   });*/

}

3)

//取消editTd编辑
function resertEditTd() {
   ready(); //此方法是自己写的,局部刷新页面,重新加载数据
}

//保存editTd编辑
function saveEditTd(id) {
   var a = $("input[type='button'][id='"+id+"']").parent().siblings(); //td的兄弟节点
   var td_name = a[1].children[0].value; //服务名称
   var td_alias = a[2].children[0].value; //服务别名
   var td_type = a[3].children[0].value; //服务类型

   var url = base_path+"console/cfg/saveEditTd";
   $.ajax({
      url:url,
      type:"post",
      data:{
         "td_name":td_name,
         "td_alias":td_alias,
         "td_type":td_type,
         "id":id,
         "tpl":configId
      },
      datatype:"json",
      success:function (result) {
         ready(); //此方法是自己写的,局部刷新页面,重新加载数据
      }
   });
}


<think>我们正在处理一个在Vue3表格中验证下拉框选择的问题。用户的需求是:在表格的某一中使用了下拉框,当点击按钮时,检查每一行的下拉框是否已选择,如果有未选择的情况,则给出提示。 解决方案思路: 1. 使用一个数组(比如`tableData`)来存储表格的数据,每一行数据中有一个属性(比如`selectedValue`)用于绑定下拉框的选中。 2. 在表格中,每一行的下拉框使用`v-model`绑定到当前行的`selectedValue`属性。 3. 在按钮点击事件中,遍历`tableData`数组,检查每一行的`selectedValue`是否有(或者是否为空,根据初始设定)。 4. 如果发现某一行没有选择,可以标记该行需要显示错误提示,并且可以设置一个全局的错误提示(比如“请确保所有行都已选择下拉框选项”)。 5. 在每一行的下拉框旁边,可以添加一个错误提示元素(比如一个红色的文字),当该行被标记为错误时显示。 具体实现步骤: 步骤1:定义表格数据 步骤2:在表格中渲染下拉框,并绑定到当前行的属性 步骤3:为每一行添加一个错误状态(比如`hasError`),用于控制是否显示错误提示 步骤4:在按钮点击事件中遍历表格数据,验证每一行的下拉框选择情况 步骤5:根据验证结果更新错误状态,并显示提示 代码示例: ```vue <template> <div> <table> <thead> <tr> <th>选项</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="(row, index) in tableData" :key="index"> <td> <select v-model="row.selectedValue"> <option disabled value="">请选择</option> <option v-for="option in options" :key="option.value" :value="option.value"> {{ option.label }} </option> </select> <span v-if="row.hasError" class="error">请选择选项</span> </td> <td> <!-- 其他操作 --> </td> </tr> </tbody> </table> <button @click="validateTable">提交</button> </div> </template> <script setup> import { ref } from 'vue'; // 下拉框选项 const options = [ { value: '1', label: '选项1' }, { value: '2', label: '选项2' }, { value: '3', label: '选项3' } ]; // 表格数据,每行有一个selectedValue属性和hasError属性 const tableData = ref([ { selectedValue: '', hasError: false }, { selectedValue: '', hasError: false }, { selectedValue: '', hasError: false } ]); // 验证表格 const validateTable = () => { let isValid = true; tableData.value.forEach(row => { if (!row.selectedValue) { row.hasError = true; isValid = false; } else { row.hasError = false; } }); if (!isValid) { // 可以在这里添加全局提示,例如使用一个toast组件 alert('请确保所有行都已选择下拉框选项'); } else { // 验证通过,执行后续操作 console.log('表格数据验证通过', tableData.value); } }; </script> <style scoped> .error { color: red; margin-left: 10px; } </style> ``` 说明: 1. 我们为每一行数据添加了`hasError`属性,用于控制该行是否显示错误提示。 2. 在`validateTable`方法中,遍历每一行,检查`selectedValue`是否为空。如果为空,则设置`hasError`为`true`,并标记整个验证为失败。 3. 如果验证失败,可以显示一个全局的提示(这里用了`alert`,实际项目中可以使用更友好的提示方式)。 4. 错误提示会显示在每一行下拉框的旁边,用红色文字提示。 优化: 1. 可以添加一个全局的错误提示,而不是每一行都显示,但为了用户能快速定位到未选择的项,每一行单独提示更友好。 2. 如果表格行数很多,可以只标记第一个未选择的项并提示,减少干扰,但这里我们选择全部标记。 使用Element Plus表格组件: 如果使用Element Plus,可以这样实现: ```vue <template> <el-table :data="tableData"> <el-table-column label="选择项"> <template #default="{ row, $index }"> <el-select v-model="row.selectedValue" placeholder="请选择" :class="{ 'error-border': row.hasError }"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <span v-if="row.hasError" class="error">请选择选项</span> </template> </el-table-column> <!-- 其他 --> </el-table> <el-button @click="validateTable">提交</el-button> </template> <script setup> import { ref } from 'vue'; const options = [ { value: '1', label: '选项1' }, { value: '2', label: '选项2' }, { value: '3', label: '选项3' } ]; const tableData = ref([ { selectedValue: '', hasError: false }, { selectedValue: '', hasError: false }, { selectedValue: '', hasError: false } ]); const validateTable = () => { let isValid = true; tableData.value.forEach(row => { if (!row.selectedValue) { row.hasError = true; isValid = false; } else { row.hasError = false; } }); if (!isValid) { // 使用Element Plus的消息提示 ElMessage.warning('请确保所有行都已选择下拉框选项'); } else { // 验证通过 console.log('验证通过'); } }; </script> <style scoped> .error { color: red; margin-left: 10px; } /* 为错误的下拉框添加红色边框 */ .error-border { :deep(.el-input__inner) { border-color: red; } } </style> ``` 注意:在Element Plus中,我们通过添加一个`error-border`类来为下拉框添加红色边框,以增强错误提示效果。由于Element Plus的样式作用域,我们可能需要使用`:deep`穿透来修改子组件的样式。 总结: 以上两种方式(原生表格和Element Plus表格)都实现了在表格中验证下拉框选择的功能。关键点在于: - 为每一行数据添加一个状态(`hasError`)来标记是否出错 - 在验证函数中遍历所有行,更新错误状态 - 在模板中根据错误状态显示提示或样式 这样,用户就能清晰地看到哪些行没有选择,从而进行修改。 [^1]: DeepSeek 助力 Vue3 开发:打造丝滑的下拉选择框(Dropdown Select)https://blog.youkuaiyun.com/qq_33650655/article/details/145861882 [^2]: 90. DeepSeek 助力 Vue3 开发:打造丝滑的表格Table)之添加行拖拽排序功能示例3,TableView16_03 拖拽视觉反馈示例 https://blog.youkuaiyun.com/qq_33650655/article/details/146517501 §§相关问题§§ 1. 如何在Vue3中实现整个表单的验证(包括表格内的表单)? 2. Element Plus中如何自定义表单验证规则? 3. Vue3中如何实现表格内嵌下拉框的远程搜索功能? 4. 如何优化Vue3表格中大量下拉框的渲染性能?</think>在 Vue3 表格中验证下拉框是否已选择,并在点击按钮时提示未选择的情况,可以通过以下步骤实现: ### 完整解决方案 ```vue <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="name" label="姓名" /> <el-table-column label="部门"> <template #default="{ row }"> <el-select v-model="row.department" placeholder="请选择部门" :class="{ 'error-border': row.showError }" > <el-option v-for="dept in departments" :key="dept.value" :label="dept.label" :value="dept.value" /> </el-select> <div v-if="row.showError" class="error-message"> 请选择部门 </div> </template> </el-table-column> </el-table> <el-button type="primary" @click="validateTable">提交表格</el-button> </template> <script setup> import { ref } from 'vue'; import { ElMessage } from 'element-plus'; // 表格数据 const tableData = ref([ { id: 1, name: '张三', department: '', showError: false }, { id: 2, name: '李四', department: '', showError: false }, { id: 3, name: '王五', department: '', showError: false } ]); // 部门选项 const departments = ref([ { value: 'dev', label: '开发部' }, { value: 'design', label: '设计部' }, { value: 'sales', label: '销售部' } ]); // 验证表格数据 const validateTable = () => { let hasError = false; // 遍历所有行,检查下拉框是否已选择 tableData.value.forEach(row => { row.showError = !row.department; // 如果没有选择,显示错误 if (!row.department) { hasError = true; } }); // 如果有未选择的项,显示全局提示 if (hasError) { ElMessage.warning({ message: '请完成所有必填项', duration: 3000 }); } else { // 所有验证通过,执行提交逻辑 console.log('表格数据验证通过', tableData.value); ElMessage.success('提交成功'); } }; </script> <style scoped> .error-message { color: #f56c6c; font-size: 12px; margin-top: 5px; } .error-border { :deep(.el-input__inner) { border-color: #f56c6c; } } </style> ``` ### 关键实现说明 1. **数据结构设计**: - 每行数据包含 `showError` 属性,用于控制该行错误提示的显示 - 下拉框绑定到 `row.department` 属性 2. **验证逻辑**: ```javascript tableData.value.forEach(row => { row.showError = !row.department; // 标记未选择的行 }); ``` 3. **错误反馈**: - 使用 `:class="{ 'error-border': row.showError }"` 为未选择项添加红色边框 - 通过 `v-if="row.showError"` 显示行内错误提示 - 使用 `ElMessage.warning` 显示全局提示 4. **用户体验优化**: - 错误提示使用醒目的红色 - 全局提示3秒后自动消失 - 成功提交时显示成功反馈 ### 高级优化方案 1. **使用自定义验证规则**: ```javascript // 在表格数据外定义验证规则 const validationRules = { department: [ { required: true, message: '部门必须选择', trigger: 'change' } ] }; // 在模板中使用 <el-form :model="row" :rules="validationRules"> <el-form-item prop="department"> <el-select v-model="row.department"> <!-- 选项 --> </el-select> </el-form-item> </el-form> ``` 2. **自动聚焦到第一个错误项**: ```javascript const validateTable = () => { // ...验证逻辑... if (hasError) { // 查找第一个错误项并聚焦 const firstErrorRow = tableData.value.find(row => row.showError); if (firstErrorRow) { nextTick(() => { const input = document.querySelector(`[data-row-id="${firstErrorRow.id}"] .el-select`); input?.focus(); }); } } }; ``` 3. **实时验证优化**: ```vue <el-select v-model="row.department" @change="row.department ? row.showError = false : null" > ``` ### 最佳实践建议 1. **复杂表单处理**: - 对于大型表格,使用 Vuex 或 Pinia 管理状态 - 考虑使用 [VeeValidate](https://vee-validate.logaretm.com/v4) 进行复杂验证: ```bash npm install vee-validate@next @vee-validate/rules ``` 2. **性能优化**: - 使用虚拟滚动处理大型表格 - 对下拉选项进行懒加载 - 使用 `shallowRef` 处理大型数据集 3. **无障碍优化**: - 为错误提示添加 `aria-describedby` 属性 - 使用 `aria-invalid="true"` 标记无效字段 - 添加键盘导航支持 [^1]: DeepSeek 助力 Vue3 开发:打造丝滑的下拉选择框(Dropdown Select)https://blog.youkuaiyun.com/qq_33650655/article/details/145861882 [^2]: 90. DeepSeek 助力 Vue3 开发:打造丝滑的表格Table)之添加行拖拽排序功能示例3,TableView16_03 拖拽视觉反馈示例 https://blog.youkuaiyun.com/qq_33650655/article/details/146517501
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值