iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0
Odoo

Odoo 14 Javascript 開發心路歷程系列 第 24

Day 24 實作 10: 建立 action client view - 增加事件(下)

  • 分享至 

  • xImage
  •  

今天來完成剩下的兩個事件 新增編輯

  • [ ] 增加事件
    • [ ] 新增
    • [ ] 編輯
    • [x] 刪除項目
    • [x] 標記完成

首先先來處理 新增 的部分,先調整模板

主要處理的部分有

  1. 增加一個 + 按鈕在最下方
  2. 在資料中增加一個 edit 狀態來記錄
  3. 判斷 id 為空時,代表為新增
<t t-name="todoList">
    <table>
        <tbody>
            <t t-if="items.length">
                <tr t-foreach="items" t-as="item">
                    <td>
                        <input type="checkbox"
                               class="finished"
                               t-att-checked="item.finished ? 'checked' : undefined"
                               t-att-data-index="item_index"/>
                    </td>
                    <td>
                        <div t-if="!item.edit" t-esc="item.name" 
														 t-att-data-index="item_index" class="todo-name"/>
                        <input t-else=""
                               type="text" class="todo-name-input"
                               t-att-value="item.name"/>
                    </td>
                    <td>
                        <i t-attf-class="fa fa-{{ item.edit ? 'check' : 'times' }}"
                           t-att-data-index="item_index"/>
                    </td>
                </tr>
            </t>
            <tr t-else="">
                <td colspan="3">
                    <span class="alert alert-success">無任何的待辦事項</span>
                </td>
            </tr>
            <tr>
                <td colspan="3" class="pt-3">
                    <button type="button" class="btn btn-info w-100 text-center btn-new-todo">
                        <i class="fa fa-plus"/>
                    </button>
                </td>
            </tr>
        </tbody>
    </table>
</t>

接著調整 JS 的部分,增加兩個事件

  1. 新增: 建立空的資料物件
  2. 存檔: 讀取結果並存到後端
'click .btn-new-todo': '_newItem',
'click i.fa-check': '_saveItem',

加入對應的函式

_newItem: function () {
    let alreadyHaveNewOne = !!this.todoList.filter(item => !item.id).length;

    if (alreadyHaveNewOne) {
        return true;
    }

    this.todoList.push({id: null, name: '', finished: false, edit: true});
    this.renderElement();

    this.el.querySelector('.todo-name-input').focus();
},

_saveItem: function (ev) {
    const self = this;
    let target = ev.currentTarget,
        data_index = target.dataset.index;

    if (!data_index) {
        return true;
    }
    let index = parseInt(data_index);

    let data = this.todoList.at(index);

    if (!data) {
        return true;
    }

    Object.assign(data, {
        name: this.el.querySelector(`input.todo-name-input`).value,
        finished: this.el.querySelector(`input[type='checkbox'][data-index="${index}"]`).checked,
    })

    this._rpc({
        model: 'todo.list',
        method: 'create',
        args: [{
            name: data.name,
            finished: data.finished,
        }]
    }).then(result => {
        if (result) {
            data.id = result;
            data.edit = false;
            self.renderElement();
        }
    });
},

新增 就完成了,是不是很簡單呢

接下來 編輯的部份,因為在新增的時候就有先把模板先改好了,就是 [item.name](http://item.name) 的部分

<div t-if="!item.edit" t-esc="item.name" 
		 t-att-data-index="item_index" class="todo-name"/>

所以接下來要調整一下 JS

一樣增加對應的事件

'click .todo-name': '_editItem',

增加對應的函式

_editItem: function (ev) {
    let target = ev.currentTarget,
        data_index = target.dataset.index;

    if (!data_index) {
        return true;
    }
    let index = parseInt(data_index);

    let data = this.todoList.at(index);

    if (!data) {
        return true;
    }

    if (!data.edit) {
        this.todoList.forEach(item => {
            if (item.edit) {
                item.edit = false;
            }
        });
        data.edit = true;

        this.renderElement();
        this.el.querySelector('.todo-name-input').focus();
    }
},

完成後重新整理網頁測試一下

咦? 編輯存檔後還是新增耶

是的,所以要調整一下 _saveItem() ,要增加判斷 id 是否為空,為空就是新增,反之則更新

_saveItem: function (ev) {
    const self = this;
    let target = ev.currentTarget,
        data_index = target.dataset.index;

    if (!data_index) {
        return true;
    }
    let index = parseInt(data_index);

    let data = this.todoList.at(index);

    if (!data) {
        return true;
    }

    let updateData = {
        name: this.el.querySelector(`input.todo-name-input`).value,
        finished: this.el.querySelector(`input[type='checkbox'][data-index="${index}"]`).checked,
    };
    Object.assign(data, updateData);

    if (data.id) {
        this._rpc({
            model: 'todo.list',
            method: 'write',
            args: [[data.id], updateData]
        }).then(result => {
            if (result) {
                data.edit = false;
                self.renderElement();
            }
        });
    } else {
        this._rpc({
            model: 'todo.list',
            method: 'create',
            args: [updateData]
        }).then(result => {
            if (result) {
                data.id = result;
                data.edit = false;
                self.renderElement();
            }
        });
    }
},

再次重新整理網頁測試後就正常了

當然我寫的程式有很多地方可以更精簡,就讓有興趣各位自行拆分職責了

最後有個小作業, _toggleFinish() 有一個很明顯的 BUG,

各位可以找一下在哪邊

Hint: 當資料為新增時,點完成會發生什麼事呢?


上一篇
Day 23 Action client view 的 renderElement() - 底層基本面講述
下一篇
Day 25 實作 11: 建立 action client view - 增加銷售訂單總和呈現的模板與資料路由
系列文
Odoo 14 Javascript 開發心路歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言