iT邦幫忙

0

jquery編輯列資料改用 vue呈現

各位大大好
有一頁面,該功能為
表單在網頁載入時ajax到後端之後取回內容並渲染
若想編輯某列的值
使用 jquery 的作法:
按下按鈕->取得該列(clickRow)->取得編輯前的值
->clone template tr (newRow)-> newRow裡input填入編輯前的值
->把newRow新增到clickRow之後

<table id="mainTB">
	<thead>
		<th>日期</th>
		<th>筆記</th>
		<th>動作</th>
	</thead>
	<tbody id="mainTBody">
		<tr>
			<td>date<td>
			<td>note<td>
			<td>
				<input type="button" name="edit" value="編輯" onclick="edit(this);">
			</td>
		</tr>
	</tbody>
</table>

<div id="template">
	<table>
		<tr name="tmpRow">
			<td><input type="date" name="noteDate"><td>
			<td><input type="text" name="noteText"><td>
			<td>
				<input type="button" name="update" value="更新">
				<input type="button" name="cancel" value="取消">
			</td>
		</tr>
	</table>
</div>

<script>
function edit(thisBtn){
	var clickRow = $(thisBtn).closest("tr").hide();	//取得編輯按鈕所屬的列 該列隱藏
	...	//取得clickRow td裡的值 (編輯前的值)
	var newRow = $("#template").find("tr[name='tmpRow']").clone();	
	...	//newRow 裡的input 填入編輯前的值
	$(clickRow).after(newRow);	//新增到要編輯的列之後
}
</script>

以jquery來說就是選擇DOM然後進行相關操作
但如果想用vue來寫
讀取後端並渲染已成功
但若想進行編輯就不曉得該怎麼做了
想請問有甚麼好的建議與做法 謝謝

<tbody>
	<tr v-for="(data, index) in notes" :key="index">
		<td>{{ data.date }}</td>
		<td>{{ data.note }}</td>
		<td>
			<input type="button" name="editBtn" value="編輯" @click="editFn">
		</td>
	</tr>
</tbody>

<script>
export default {
  data () {
    return {
      notes: null,
    }
  },
  methods: {
    async loadPage(){
      try{
        let response = await this.$http.get(`...`);
        this.notes = response.data;
      } catch(err){
        window.alert(err)
      }
    },
    editFn(){
		//產生編輯列
	},

  },
  async created () {
    this.loadPage()
  }
}
</script>

froce iT邦大師 1 級 ‧ 2020-08-11 11:28:49 檢舉
直接編輯資料即可,你問這個我覺得你vue根本還沒弄懂
xSummer iT邦新手 4 級 ‧ 2020-08-11 13:25:03 檢舉
了解 謝謝你的指教

2 個回答

1
通靈亡
iT邦研究生 5 級 ‧ 2020-08-11 10:13:02
最佳解答

編輯欄位設定v-model,將每一列的資料帶到@click事件,更新欄位的v-model

<!--template-->
<input type="button" name="editBtn" value="編輯" @click="editFn(index, data)">

<input type="date" v-model="model.noteDate" name="noteDate">
<input type="text" v-model="model.noteText" name="noteText">

// data
model: {
  index: null,
  noteDate: null,
  noteText: null
},

// methods
editFn (index, data) {
    this.model.index = index;
    this.model.noteDate = data.date;
    this.model.noteText = data.note;
},

編輯完後,將v-model的值,塞回特定index的資料,即可更新編輯的資料

<!--template-->
<input type="button" name="update" value="更新" @click="updateRow">

// methods
updateRow () {
   this.notes[this.model.index].date = this.model.noteDate;
   this.notes[this.model.index].note = this.model.noteText;
}

參考Sample:

<template>
    <div>
        <table>
            <thead>
                <th>日期</th>
                <th>筆記</th>
                <th>動作</th>
            </thead>
            <tbody>
                <template v-for="(data, index) in notes">
                    <tr>
                        <td>{{ data.date }}</td>
                        <td>{{ data.note }}</td>
                        <td>
                            <input type="button" name="editBtn" value="編輯" @click="editFn(index, data)">
                        </td>
                    </tr>
                    <tr name="tmpRow" v-if="model.index === index">
                        <td><input type="date" v-model="model.noteDate" name="noteDate"></td>
                        <td><input type="text" v-model="model.noteText" name="noteText"></td>
                        <td>
                            <input type="button" name="update" value="更新" @click="updateRow">
                            <input type="button" name="cancel" value="取消" @click="clearTempRow">
                        </td>
                    </tr>
                </template>
            </tbody>
        </table>
    </div>
</template>


<script>
export default {
  data () {
    return {
      model: {
          index: null,
          noteDate: null,
          noteText: null
      },
      notes: null,
    }
  },
  methods: {
    async loadPage () {
      try{
        let response = await this.$http.get(`...`);
        this.notes = response.data;
      } catch(err){
        window.alert(err)
      }
    },
    editFn (index, data) {
        this.model.index= index;
		this.model.noteDate = data.date;
        this.model.noteText = data.note;
	},
    updateRow () {
        this.notes[this.model.index].date = this.model.noteDate;
        this.notes[this.model.index].note = this.model.noteText;
        this.clearTempRow();
    },
    clearTempRow () {
        this.model.index = null;
		this.model.noteDate = null;
        this.model.noteText = null;
    }
  },
  async created () {
    this.loadPage()
  }
}
</script>
看更多先前的回應...收起先前的回應...
xSummer iT邦新手 4 級 ‧ 2020-08-11 11:30:31 檢舉

謝謝回答
我想請問一下 大大是會怎樣產生出編輯列

通靈亡 iT邦研究生 5 級 ‧ 2020-08-11 11:37:02 檢舉

原則上Vue的思維,大多時候你不需要自行處理任何DOM Tree的節點操作
Vue的思維比較偏向,當資料(data、computed、watch)在什麼狀態下,畫面(template)該怎麼呈現

關於編輯列顯示隱藏的部分
我是預先寫好在Vue Template當中,使用v-show控制在編輯的時候才顯示
當你按下編輯時,model.index !== null 編輯列就會顯示
當你完成編輯後,model.index === null 編輯列就不會顯示

<!--model.index !== null (編輯時),才顯示編輯列-->
<tr name="tmpRow" v-show="model.index !== null">

</tr>

另外補充一下,也可以使用v-if,但兩者不太一樣:

  1. v-show,條件不成立時,透過CSS display = none隱藏,節點仍存在
  2. v-if,條件成立時,會從DOM Tree將節點移除

如果你不希望編輯列的HTML存在,就可以改使用v-if

xSummer iT邦新手 4 級 ‧ 2020-08-11 11:48:01 檢舉

可是這樣的話不管是編輯哪一列 編輯列都會出現在表單的最下面 對吧? 有辦法出現在欲編輯列的下面嗎?

通靈亡 iT邦研究生 5 級 ‧ 2020-08-11 12:18:39 檢舉

如果你要改成在指定列下方的話,可以使用 <template> 包住兩個tr
一個是資料列,一個是編輯列
編輯列再用v-if判斷,判斷是否顯示正在編輯的資料

https://ithelp.ithome.com.tw/upload/images/20200811/20120331swWoUK4rYy.png

<tbody>
    <template v-for="(data, index) in notes">
        <tr>
            <td>{{ data.date }}</td>
            <td>{{ data.note }}</td>
            <td>
                <input type="button" name="editBtn" value="編輯" @click="editFn(index, data)">
            </td>
        </tr>
        <tr name="tmpRow" v-if="model.index === index">
            <td><input type="date" v-model="model.noteDate" name="noteDate"></td>
            <td><input type="text" v-model="model.noteText" name="noteText"></td>
            <td>
                <input type="button" name="update" value="更新" @click="updateRow">
                <input type="button" name="cancel" value="取消" @click="clearTempRow">
            </td>
        </tr>
    </template>
</tbody>
xSummer iT邦新手 4 級 ‧ 2020-08-11 13:23:26 檢舉

謝謝回答 我知道關鍵所在了

2
listennn08
iT邦高手 9 級 ‧ 2020-08-11 10:44:19

這應該比你使用 jQuery 的時候好寫很多
codepen

xSummer iT邦新手 4 級 ‧ 2020-08-11 13:23:09 檢舉

謝謝回答 大大做法我大約了解了

通靈亡 iT邦研究生 5 級 ‧ 2020-08-11 15:00:52 檢舉

listennn08
你一開始寫的版本我覺得也不錯,而且比較直觀
直接原資料列替換input跟文字

通靈亡
他說要放下面所以我就改成放下面的版本XD
然後有想到如果不要替換要能變成替換前的值,又多存了改變之前的值
不然用 v-model 就會直接換掉了

我要發表回答

立即登入回答