Xóa Record

Tính năng tiếp theo chúng ta cần thực hiện đó là xóa record từ database. Với tính năng này chúng ta sẽ cần cập nhật UI bằng việc thêm một button để khi click vào sẽ thực hiện việc gửi request xóa record lên server. Ngoài ra chúng ta cũng cần cập nhật code trong Rails để server có thể xử lý việc xóa record.

Thêm Action vào Controller

Đầu tiên chúng ta sẽ cần cập nhật code trong Rails để thêm logic xử lý việc xóa record. Mở file chứa class RecordsController bạn thêm method destroy như sau:

  def destroy
    @record = Record.find(params[:id])
    @record.destroy
    head :no_content
  end

Lưu thay đổi trên và khởi động lại server.

Thêm Delete Button

Sau khi đã thêm method xử lý việc xóa record thì công việc tiếp theo chúng ta cần làm đó là thêm button để xóa record trên UI. Đầu tiên cập nhật method render() trong Records component như sau:

# app/assets/javascripts/components/records.js.coffee

  @Records = React.createClass
    ...
    render: ->
      ...
      # almost at the bottom of the render method
      React.DOM.table
        React.DOM.thead null,
          React.DOM.tr null,
            React.DOM.th null, 'Date'
            React.DOM.th null, 'Title'
            React.DOM.th null, 'Amount'
            React.DOM.th null, 'Actions'
        React.DOM.tbody null,
          for record in @state.records
            React.createElement Record, key: record.id, record: record

Code JavaScript:

  React.DOM.table({
    className: 'table table-bordered'
  }, React.DOM.thead(null, React.DOM.tr(null, React.DOM.th(null, 'Date'), React.DOM.th(null, 'Title'), React.DOM.th(null, 'Amount'), React.DOM.th(null, 'Actions'))), React.DOM.tbody(null, (function() {
  ...

Đoạn code trên đơn giản thêm một thẻ <th>Actions</th> vào thẻ <tr> của <thead>.

Tiếp theo bạn cần tạo một thẻ <td> tương ứng với thẻ <th> mởi được thêm ở trên:

  # app/assets/javascripts/components/record.js.coffee

  @Record = React.createClass
    render: ->
      React.DOM.tr null,
        React.DOM.td null, @props.record.date
        React.DOM.td null, @props.record.title
        React.DOM.td null, amountFormat(@props.record.amount)
        React.DOM.td null,
          React.DOM.a
            className: 'btn btn-danger'
            'Delete'

Code JavaScript:

...
    render: function() {
      return {
        render: function() {
          return React.DOM.tr(null, React.DOM.td(null, this.props.record.date), React.DOM.td(null, this.props.record.title), React.DOM.td(null, amountFormat(this.props.record.amount)), React.DOM.td(null, React.DOM.a({
            className: 'btn btn-danger'
          }, 'Delete')));
        }
      };
    }
...

Bây giờ nếu tải lại trang bạn sẽ thấy trình duyệt hiển thị kết quả như hình phía dưới:

Thêm delete button

Xóa Record Khi Click Button

Tới đây chúng ta đã thêm Delete button vào trang, tuy nhiên button mới được thêm ở trên chưa thực hiện bất cứ hành động nào nếu bạn click vào bởi vì chúng ta đơn giản mới thêm HTML cho nó. Để button này lắng nghe sự kiện click chúng ta sẽ cần thêm method onClick() như sau:


  # app/assets/javascripts/components/record.js.coffee
  @Record = React.createClass
    render: ->
      React.DOM.tr null,
        React.DOM.td null, @props.record.date
        React.DOM.td null, @props.record.title
        React.DOM.td null, amountFormat(@props.record.amount)
        React.DOM.td null,
          React.DOM.a
            className: 'btn btn-danger'
            onClick: @handleDelete
            'Delete'

Và đồng thời method handleDelete() cho component này:


  # app/assets/javascripts/components/record.js.coffee

  @Record = React.createClass
    handleDelete: (e) ->
      e.preventDefault()
      # yeah... jQuery doesn't have a $.delete shortcut method
      $.ajax
        method: 'DELETE'
        url: "/records/#{ @props.record.id }"
        dataType: 'JSON'
        success: () =>
          @props.handleDeleteRecord @props.record

Code JavaScript:

...
    handleDelete: function(e) {
      e.preventDefault();
      return $.ajax({
        method: 'DELETE',
        url: "/records/" + this.props.record.id,
        dataType: 'JSON',
        success: (function(_this) {
          return function() {
            return _this.props.handleDeleteRecord(_this.props.record);
          };
        })(this)
      });
    },
...

Với đoạn code trên thì khi người dùng click vào button, trình duyệt sẽ gửi một AJAX request sử dụng HTTP method là DELETE và tới URL như sau:

"/records/" + this.props.record.id

URL ở trên theo format của RESTful API /records/{id} và giá trị id được lấy từ property id của record tương ứng muốn xóa.

Điểm cuối cùng bạn cần chú ý đó là trong hàm success callback của AJAX request trên chúng ta gọi một hàm được gán vào giá trị của property handleDeleteRecord của Record component. Property này ở đâu ra? Câu trả lời khá giống với cách làm ở những phần trước, chúng ta sẽ gán giá trị cho property này từ Records component:

  # app/assets/javascripts/components/records.js.coffee

  @Records = React.createClass
    ...
    render: ->
      ...
      React.DOM.table
        React.DOM.thead null,
          React.DOM.tr null,
            React.DOM.th null, 'Date'
            React.DOM.th null, 'Title'
            React.DOM.th null, 'Amount'
            React.DOM.th null, 'Actions'
        React.DOM.tbody null,
          for record in @state.records
            React.createElement Record, key: record.id, record: record, handleDeleteRecord: @deleteRecord

Ở trên chúng ta gán giá trị cho property handleDeleteRecord của Record lấy giá trị từ property deleteRecord của Record component. Và do đó chúng ta sẽ cần thêm property này vào Records component:

  # app/assets/javascripts/components/records.js.coffee

  @Records = React.createClass
    ...
    deleteRecord: (record) ->
      records = @state.records.slice()
      index = records.indexOf record
      records.splice index, 1
      @replaceState records: records
    render: ->
    ...

Code JavaScript:

...
    deleteRecord: function(record) {
      var index, records;
      records = this.state.records.slice();
      index = records.indexOf(record);
      records.splice(index, 1);
      return this.replaceState({
        records: records
      });
    },

Trong đoạn code trên giá trị cho property deleteRecord của Records component được gán cho một hàm và hàm này có nhiệm vụ cập nhật lại state cho component này.

Bạn cũng chú ý ở trên chúng ta sử dụng method replaceState() của React để thiết lập lại state thay vì sử dụng method setState() cũng có trong React. Sự khác biệt ở đây đó là setSate() sẽ update một key trong state của component (ở trong Records component hiện tại chúng ta có một key state là records). Ngược lại replaceState() sẽ thiết lập lại toàn bộ tất cả các key của state với giá trị của đối số truyền vào cho method này.

Bây giờ nếu bạn tải lại trang và click vào một trong số các Delete button có trong cột Actions bạn sẽ thấy trình duyệt sẽ gần như ngay lập tức xóa bỏ dòng tương ứng chứa button đó trong bảng.

Xây Dựng Ứng Dụng Quản Lý Chi Phí Với Rails...

Câu Hỏi
Chưa có câu hỏi nào cho bài hướng dẫn này
Đặt Câu Hỏi
Mời Bạn Bè
Gửi email mời bạn bè
Viết Cùng Tác Giả
Bạn biết về chủ đề này và muốn tham gia viết cùng tác giả?