【问题标题】:How to load json data to DataTable with editable rows?如何将 json 数据加载到具有可编辑行的 DataTable?
【发布时间】:2017-02-04 13:22:39
【问题描述】:

伙计们需要您的专家建议, 我正在关注这个关于使用数据表插件的示例,只是想知道是否可以使用 ajax 编辑行的操作来填充表?

到目前为止我得到的代码是这样的。此代码成功创建了输入元素并保存了数据表的链接,但我不确定将 ajax 加载函数放在哪里。

(function( $ ) {

'use strict';

var EditableTable = {

    options: {
        addButton: '#addToTable',
        table: '#branches-editable',
        dialog: {
            wrapper: '#dialog',
            cancelButton: '#dialogCancel',
            confirmButton: '#dialogConfirm',
        }
    },

    initialize: function() {
        this
            .setVars()
            .build()
            .loadData()
            .events();
    },

    setVars: function() {
        this.$table             = $( this.options.table );
        this.$addButton         = $( this.options.addButton );

        // dialog
        this.dialog             = {};
        this.dialog.$wrapper    = $( this.options.dialog.wrapper );
        this.dialog.$cancel     = $( this.options.dialog.cancelButton );
        this.dialog.$confirm    = $( this.options.dialog.confirmButton );

        return this;
    },

    build: function() {
        this.datatable = this.$table.DataTable({
            aoColumns: [
                null,
                null,
                null,
                null,
                { "bSortable": false }
            ]
        });

        window.dt = this.datatable;
        return this;
    },

    // Trying to load my json data here but getting an error saying
    // DataTables warning: table id=branches-editable - 
    // Cannot reinitialise DataTable. For more information about this error, 
    // please see http://datatables.net/tn/3
    loadData: function() {
        this.datatable = this.$table.DataTable({
            bProcessing: true,
            sAjaxSource: this.$table.data('url')
        });
    },

    events: function() {
        var _self = this;

        this.$table
            .on('click', 'a.save-row', function( e ) {
                e.preventDefault();

                _self.rowSave( $(this).closest( 'tr' ) );
            })
            .on('click', 'a.cancel-row', function( e ) {
                e.preventDefault();

                _self.rowCancel( $(this).closest( 'tr' ) );
            })
            .on('click', 'a.edit-row', function( e ) {
                e.preventDefault();

                _self.rowEdit( $(this).closest( 'tr' ) );
            })
            .on( 'click', 'a.remove-row', function( e ) {
                e.preventDefault();

                var $row = $(this).closest( 'tr' );

                $.magnificPopup.open({
                    items: {
                        src: _self.options.dialog.wrapper,
                        type: 'inline'
                    },
                    preloader: false,
                    modal: true,
                    callbacks: {
                        change: function() {
                            _self.dialog.$confirm.on( 'click', function( e ) {
                                e.preventDefault();

                                _self.rowRemove( $row );
                                $.magnificPopup.close();
                            });
                        },
                        close: function() {
                            _self.dialog.$confirm.off( 'click' );
                        }
                    }
                });
            });

        this.$addButton.on( 'click', function(e) {
            e.preventDefault();

            _self.rowAdd();
        });

        this.dialog.$cancel.on( 'click', function( e ) {
            e.preventDefault();
            $.magnificPopup.close();
        });

        return this;
    },

    // ==========================================================================================
    // ROW FUNCTIONS
    // ==========================================================================================
    rowAdd: function() {
        this.$addButton.attr({ 'disabled': 'disabled' });

        var actions,
            data,
            $row;

        actions = [
            '<a href="#" class="hidden on-editing save-row"><i class="fa fa-save"></i></a>',
            '<a href="#" class="hidden on-editing cancel-row"><i class="fa fa-times"></i></a>',
            '<a href="#" class="on-default edit-row"><i class="fa fa-pencil"></i></a>',
            '<a href="#" class="on-default remove-row"><i class="fa fa-trash-o"></i></a>'
        ].join(' ');

        data = this.datatable.row.add([ '', '', '', '', actions ]);
        $row = this.datatable.row( data[0] ).nodes().to$();

        $row
            .addClass( 'adding' )
            .find( 'td:last' )
            .addClass( 'actions' );

        this.rowEdit( $row );

        this.datatable.order([0,'asc']).draw(); // always show fields
    },

    rowCancel: function( $row ) {
        var _self = this,
            $actions,
            i,
            data;

        if ( $row.hasClass('adding') ) {
            this.rowRemove( $row );
        } else {

            data = this.datatable.row( $row.get(0) ).data();
            this.datatable.row( $row.get(0) ).data( data );

            $actions = $row.find('td.actions');
            if ( $actions.get(0) ) {
                this.rowSetActionsDefault( $row );
            }

            this.datatable.draw();
        }
    },

    rowEdit: function( $row ) {
        var _self = this,
            data;

        data = this.datatable.row( $row.get(0) ).data();

        $row.children( 'td' ).each(function( i ) {
            var $this = $( this );

            if ( $this.hasClass('actions') ) {
                _self.rowSetActionsEditing( $row );
            } else {
                $this.html( '<input type="text" class="form-control input-block" value="' + data[i] + '"/>' );
            }
        });
    },

    rowSave: function( $row ) {
        var _self     = this,
            $actions,
            values    = [];

        if ( $row.hasClass( 'adding' ) ) {
            this.$addButton.removeAttr( 'disabled' );
            $row.removeClass( 'adding' );
        }

        values = $row.find('td').map(function() {
            var $this = $(this);

            if ( $this.hasClass('actions') ) {
                _self.rowSetActionsDefault( $row );
                return _self.datatable.cell( this ).data();
            } else {
                return $.trim( $this.find('input').val() );
            }
        });

        this.datatable.row( $row.get(0) ).data( values );

        $actions = $row.find('td.actions');
        if ( $actions.get(0) ) {
            this.rowSetActionsDefault( $row );
        }

        this.datatable.draw();
    },

    rowRemove: function( $row ) {
        if ( $row.hasClass('adding') ) {
            this.$addButton.removeAttr( 'disabled' );
        }

        this.datatable.row( $row.get(0) ).remove().draw();
    },

    rowSetActionsEditing: function( $row ) {
        $row.find( '.on-editing' ).removeClass( 'hidden' );
        $row.find( '.on-default' ).addClass( 'hidden' );
    },

    rowSetActionsDefault: function( $row ) {
        $row.find( '.on-editing' ).addClass( 'hidden' );
        $row.find( '.on-default' ).removeClass( 'hidden' );
    }
};

$(function() {
    EditableTable.initialize();
});

}).apply( this, [ jQuery ]);

【问题讨论】:

  • 获得正确的编辑功能(在字段中添加输入,正确搜索这些输入,将呈现的表与服务器数据同步,在分页数据时跟上更改的行等......)是一切皆有可能。但是,对于这个网站来说,它并不简单,而且过于宽泛。
  • 谢谢您的回复先生,您能给一些建议还是我的代码有问题?这些在他们网站的示例页面中,我只是将它们放在一起。
  • 嗨,理查德,对于它的价值,我在下面留下了一个答案,应该会让你走上正轨。 :)

标签: javascript jquery json ajax datatable


【解决方案1】:

根据经验,已经构建了您之前要求的内容(具有完全可编辑行的 Datatables 实现)我可以告诉您,您现在遇到的问题“无法重新初始化 DataTable”只是您遇到的众多问题中的第一个将遇到这个项目。这是可行的,但是您需要解决一些超出此问题范围的问题(稍后将详细介绍)。

您在这里的具体问题是您正试图重新重新初始化您的数据表,正如错误所述,您不能这样做。您可以做的是reload 数据表datatable.ajax.reload() 之类的,或者,如果您只想使用当前数据重新draw(可能是为了清除更改)dataTable.rows().invalidate().draw(); 之类的东西

例如,以下是我自己的实现中的函数,它们初始化和重绘我的表以避免您面临的问题:

initDataTable:function(){
    var _this=this;
    if(_this.options.trackRowsWithChanges){
        _this.trackRowsWithChanges();
    }
    if(!_this.dataTable) _this.dataTable=$(_this.options.tableId).DataTable(_this.options.dataTableOptions);
    if(_this.options.useLiveDomSort){
        _this.useLiveDomSort();
    }
    return _this.dataTable;
},

redrawTable:function(fromServer,sortOrder){
    var _this=this;
    fromServer ?  _this.dataTable.ajax.reload() : _this.dataTable.rows().invalidate().draw();
    if(sortOrder) _this.dataTable.order([ 0, 'desc' ],[ 1, 'asc' ]).draw()

}

当然,就像我提到的,还会有其他问题,例如:

  • 使用默认数据表搜索功能无法正确搜索您的行,您必须使用自己的搜索功能扩展数据表,以考虑获取输入值而不是列文本。
  • 由于分页,您需要跟踪内部数据表数据的更改,而不仅仅是在可见 ui 中。更改第一页上的值,然后移动第二页,然后向后移动,您的更改将消失,因为数据表仅在 UI 中绘制行的当前“页面”,并且在更改页面时它们会被销毁并重新创建。
  • 添加新行是.....有问题,您不想按照开始的方式对其进行硬编码,使其根据实际数据动态添加它们,相信我,当您使用此代码时,您会感谢我不同的数据表;)
  • 始终将新添加的行添加到您可以看到的表格顶部(而不是像最后一个隐藏页面的中间那样)并非易事,您需要精确控制排序才能正常工作李>
  • 默认情况下,不正确支持在单元格之间切换和登陆输入,您需要编写一些 shim 来使其工作,但按照您的用户期望的那样工作

我不能轻易地让你成为一个工作示例(id 必须创建一个数据库并设置所有这些)但是,如果你有兴趣,请告诉我,我会以文件的形式与你分享我的完整实现。

【讨论】:

  • 查看x-editable 可能很有用,我设法将它集成到数据表中,并且效果很好。完全可编辑的列。
  • @Sebastianb 很有趣,该插件如何处理我上面提到的分页问题?你如何处理添加行?
  • 好吧,插件会在每次绘制时重新初始化(使用 fnDrawCallback)在特定的 tr 上,因此仅此一项就可以更轻松地添加/删除行(tabla.row.add(data).draw() 就足够了,对于删除),关于分页,我猜是 drawCallback 和插件也改变了 DOM 的内容这一事实使它一切正常。
  • 请注意,已经有一段时间了,所以可能有一些代码潜伏在我现在无法捕捉到的地方;)
  • 哦,过滤器/搜索功能继续工作,因为 x-editable 在您单击/双击之前不会更改单元格的内容。就在那时,DOM 得到更新,并显示一个输入字段。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-01
  • 2018-10-13
  • 2011-07-05
  • 1970-01-01
  • 2021-07-31
  • 1970-01-01
  • 2017-06-20
相关资源
最近更新 更多