Skip to content
This repository was archived by the owner on Feb 2, 2025. It is now read-only.

Angular-datatable responsive plugin ng-click incompatibility #305

Closed
mzaarour opened this issue Apr 29, 2015 · 22 comments
Closed

Angular-datatable responsive plugin ng-click incompatibility #305

mzaarour opened this issue Apr 29, 2015 · 22 comments

Comments

@mzaarour
Copy link

Hi,

Thank you for your very interesting angular plugin for datatables. I am now facing a problem which is :
My conf :

  • angular-datatables v0.4.0
  • angular v1.3.13
  • dataTables.responsive 1.0.4

The issue :

  • i have added to my datatables 2 action buttons "open" and "Delete"
  • those buttons works well on big screen (like a desktop)
  • when i reduce the screen or simply display on a small = the responsive hide all over columns ==> OK works well
  • but, the hidden columns buttons don't work with ng-click action ==> NOK
  • I think that is because responsive plugin modify the DOM which escape to angular's scope

==> I am looking for a function (like a listener) which will allow me to $compile all columns after responsible function.
Have you got another solution ?

Thank you in advance for your help

@l-lin
Copy link
Owner

l-lin commented May 4, 2015

Have you tried using the datatables response.details.renderer?

@mzaarour
Copy link
Author

mzaarour commented May 4, 2015

Hi,

Thank you for your answer. I wanted to use it but i don't know how i can get it !

may be with this code ? isn't it to late ?

DTInstances.getLast().then(function (dtInstance) {
$scope.dtInstance = dtInstance;
});

while initialization but how ? $scope.dtOptions ?

Thank you for your help

@l-lin
Copy link
Owner

l-lin commented May 5, 2015

Mmh I'm not sure you can do it, unfortunately.
Indeed, using the datatables response.details.renderer, I thought it would be the same as my rowClickEvent example, however, the responsive plugin does not an equivalent as the rowCallback.

So it should be possible, but in a really hackish way (using jquery, parsing the HTML, compiling with Angular and such). I do not recommend going this path as it may produce not only a code that will not be readable but also some performance issues.

@mzaarour
Copy link
Author

mzaarour commented May 5, 2015

Hi,

yes, jquery is the ultimate of ultimate solution and i confess that i don't want to use it. I'll try as you said and will make you a feedback if i got something new.

Anyway, the temporary solution is to put buttons column among the first columns.

Thank you for all
You can close this issue.

@mzaarour mzaarour closed this as completed May 5, 2015
@tahirsaleem
Copy link

@mzaarour did you get a solution to your issue?
I am facing the same problem.. ng-click is not working under responsive (compact) view.

@mzaarour
Copy link
Author

Hi,

No i went to the solution that not compact the actions column's button ,
the most simple solution :-)
If you want to work on it, i will be happy !

See you

Le 28/07/2015 13:22, tahirsaleem a écrit :

@mzaarour https://github.com/mzaarour did you get a solution to your
issue?
I am facing the same problem.. ng-click is not working under
responsive (compact) view.


Reply to this email directly or view it on GitHub
#305 (comment).

@tahirsaleem
Copy link

Ok.. so did you make the action column as the first column of the table?or some other way? Let me know if you have any example or code snippetthat you can share?
Thanks.
Tahir

Date: Tue, 28 Jul 2015 04:57:39 -0700
From: [email protected]
To: [email protected]
CC: [email protected]
Subject: Re: [angular-datatables] Angular-datatable responsive plugin ng-click incompatibility (#305)

Hi,

No i went to the solution that not compact the actions column's button ,

the most simple solution :-)

If you want to work on it, i will be happy !

See you

Le 28/07/2015 13:22, tahirsaleem a écrit :

@mzaarour https://github.com/mzaarour did you get a solution to your

issue?

I am facing the same problem.. ng-click is not working under

responsive (compact) view.

Reply to this email directly or view it on GitHub

#305 (comment).


Reply to this email directly or view it on GitHub.

@mzaarour
Copy link
Author

Yes, i put the action column at max the third column, so that the
responsive compact not occurs on it.

Le 28/07/2015 14:01, tahirsaleem a écrit :

Ok.. so did you make the action column as the first column of the
table?or some other way? Let me know if you have any example or code
snippetthat you can share?
Thanks.
Tahir

Date: Tue, 28 Jul 2015 04:57:39 -0700
From: [email protected]
To: [email protected]
CC: [email protected]
Subject: Re: [angular-datatables] Angular-datatable responsive plugin
ng-click incompatibility (#305)

Hi,

No i went to the solution that not compact the actions column's button ,

the most simple solution :-)

If you want to work on it, i will be happy !

See you

Le 28/07/2015 13:22, tahirsaleem a écrit :

@mzaarour https://github.com/mzaarour did you get a solution to your

issue?

I am facing the same problem.. ng-click is not working under

responsive (compact) view.

Reply to this email directly or view it on GitHub

#305 (comment).


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub
#305 (comment).

@tahirsaleem
Copy link

OK.. I will try to replicate that and see how it looks.
Thanks.

Date: Tue, 28 Jul 2015 05:05:29 -0700
From: [email protected]
To: [email protected]
CC: [email protected]
Subject: Re: [angular-datatables] Angular-datatable responsive plugin ng-click incompatibility (#305)

Yes, i put the action column at max the third column, so that the

responsive compact not occurs on it.

Le 28/07/2015 14:01, tahirsaleem a écrit :

Ok.. so did you make the action column as the first column of the

table?or some other way? Let me know if you have any example or code

snippetthat you can share?

Thanks.

Tahir

Date: Tue, 28 Jul 2015 04:57:39 -0700

From: [email protected]

To: [email protected]

CC: [email protected]

Subject: Re: [angular-datatables] Angular-datatable responsive plugin

ng-click incompatibility (#305)

Hi,

No i went to the solution that not compact the actions column's button ,

the most simple solution :-)

If you want to work on it, i will be happy !

See you

Le 28/07/2015 13:22, tahirsaleem a écrit :

@mzaarour https://github.com/mzaarour did you get a solution to your

issue?

I am facing the same problem.. ng-click is not working under

responsive (compact) view.

Reply to this email directly or view it on GitHub

#305 (comment).

Reply to this email directly or view it on GitHub.

Reply to this email directly or view it on GitHub

#305 (comment).


Reply to this email directly or view it on GitHub.

@mzaarour
Copy link
Author

It is easy to replicate it. I would like to share the code but it's a
confidential project. You can send me a begining of code, i will
replicate it. It would be a pleasure if i can help you.

Le 28/07/2015 14:06, tahirsaleem a écrit :

OK.. I will try to replicate that and see how it looks.
Thanks.

Date: Tue, 28 Jul 2015 05:05:29 -0700
From: [email protected]
To: [email protected]
CC: [email protected]
Subject: Re: [angular-datatables] Angular-datatable responsive plugin
ng-click incompatibility (#305)

Yes, i put the action column at max the third column, so that the

responsive compact not occurs on it.

Le 28/07/2015 14:01, tahirsaleem a écrit :

Ok.. so did you make the action column as the first column of the

table?or some other way? Let me know if you have any example or code

snippetthat you can share?

Thanks.

Tahir

Date: Tue, 28 Jul 2015 04:57:39 -0700

From: [email protected]

To: [email protected]

CC: [email protected]

Subject: Re: [angular-datatables] Angular-datatable responsive plugin

ng-click incompatibility (#305)

Hi,

No i went to the solution that not compact the actions column's button ,

the most simple solution :-)

If you want to work on it, i will be happy !

See you

Le 28/07/2015 13:22, tahirsaleem a écrit :

@mzaarour https://github.com/mzaarour did you get a solution to your

issue?

I am facing the same problem.. ng-click is not working under

responsive (compact) view.

Reply to this email directly or view it on GitHub

#305 (comment).

Reply to this email directly or view it on GitHub.

Reply to this email directly or view it on GitHub

#305 (comment).


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub
#305 (comment).

@brianmyler
Copy link

Although I would prefer that the click event was not lost when the control is moved to the child view and am surprised this has been closed, there is a way around it. Similar to @mzaarour suggestion above where the action column is placed at max the third column in the table, we can in fact place our control in any column we want and use a class to tell datatables responsive to never allow that column to become responsive i.e moved to the child row.

This can be achieved by using something similar to the following in your table headers

<th>aaa</th>
<th>bbb</th>
<th>ccc</th>
<th>ddd</th>
<th>eee</th>
<th>fff</th>
<th>ggg</th>
<th class="all"><button type="button" id="hhh" value="blah"/></th>

This means that the first 7 columns can be added to the child row, but the 8th, the button, cannot, therefore guaranteeing the button always stays in the parent row, no matter what column it is in

Hope this helps

@marcokorb
Copy link

Hi,

First, sorry for my english.

I don't know if this issue has already been solved but i found a way to keep the click event with responsive plugin using datatables response.details.renderer.

I'm using renderWith option to customize the rows.

In this link from datatables https://datatables.net/reference/option/responsive.details.renderer,
the documention says that responsive plugin receives an object and this object has a property renderer. The renderer property receives a function to render the child rows.

var responsive = {details: {renderer: rendererRows}};
DTOptionsBuilder
    .newOptions()
    .withOption('ajax', ajaxRequest)
        .withDataProp('data')
        .withOption('processing', true)
    .withOption('serverSide', true)
    .withOption('order', [[1, 'asc']])
    .withOption('bFilter', false)
    .withOption('bLengthChange', false)
    .withOption('responsive', responsive)
    .withLanguage(LANGUAGE_DATA_TABLE)
    .withPaginationType('simple_numbers');

When setting a value to 'responsive' option I used an object.
Then I overrided the renderer method.

function rendererRows( api, rowIndex ) {

        /**
         *
         * Override the default renderer for child's rows.
         *
         * @params {object}: API instance from datatable
         * @params {int}: Contains the row index
         *
         * @type {*|string}
         **/

         var data = api.( rowIndex, ':hidden' ).eq(0).map( renderCell ).toArray().join('');

          function renderCell( cell ) {

                /**
                 *
                 * Render the childs columns keeping the events used in
                 * @renderWith option.
                 *
                 * @params {object}: Cell api instance from datatables.
                 *
                 * @return {string}: The child's row html.
                 *
                 **/

                var header, _cell, cellData, index, column, columnData, rowObject;

                // gets the header
                header = angular.element(api.column(cell.column).header());

                // gets the target cell from map
                _cell = api.cell(cell);

                // gets the cell's data
                cellData = _cell.data();

                // gets the indexes info
                // @index is an object with row and column index
                index = _cell.index();

                // gets the angular-datable column instance.
                column = _cell.context[0].aoColumns[index.column];

                // gets the object that is filling the table row information
                rowObject = _cell.context[0].aoData[index.row]._aData;

                // checks if the @renderWith is a function
                if(angular.isFunction(column.mRender)) {

                    columnData = column.mRender(cellData, null, rowObject);
                } else {

                    columnData = cellData;
                }

                // create the new row template
                var template = '<tr>'+
                               '    <td><b>'+
                                     header.text() + ':' +
                               '    </b></td>'+
                               '    <td> '+
                                     columnData+
                               '    </td>'+
                               '</tr>';

                return template;
            }

            // gets the table and append the rows
            var table = angular
                            .element('<table/>')
                            .append(data);

            // compile the table to keep the events
            $compile(table.contents())($scope);

            return table;
 }

I don't know if this is the best way to keep the events but it fixed my problem.
I think @l-lin could tell if this is a bad or good way @mzaarour @brianmyler .

Hope can help.

@Hansel03
Copy link

The solution @brianmyler works for me

@rachellcarbone
Copy link

Thank you so much @marcokorb !
I had been trying to use $compile(table)($scope); instead of $compile(table.contents())($scope); and it was causing an infinite loop.

@durhaya
Copy link

durhaya commented Feb 10, 2016

I had faced the same issue.
I had some action buttons in last column of angular-datatable. In responsive view ng-click was not working.
I replaced ng-click with onclick.
To do this, I wrote a javascript function outside the scope say DeleteEvent(). Called this function on onclick.
Further in DeleteEvent function, I called my scope function which was called in ng-click.

function DeleteEvent(id) {
angular.element(document.getElementById('tblEvents')).scope().deleteRow(id);
}

Sample code file is attached.
sampleCode.txt

@fabiogel
Copy link

Thanks @brianmyler. Its perfect for me.

@unluckynelson
Copy link

unluckynelson commented Jul 24, 2016

@brianmyler Should be the only solution! Works for me too simply add a class="all" to the col heading

@chrisparton1991
Copy link

chrisparton1991 commented Aug 3, 2016

I've created a solution that works for my particular case, I thought I'd share it.

All of my datatables are wrapped in a directive that does some extra setup. In its link method, I register a click handler using jQuery, and do the compile on the fly, passing in scope.$parent. The use of the parent scope is an assumption that works for my use case, but may not work in all circumstances.

On the plus side, this solution works for tables that have lots of columns with buttons.

Additionally, the code may result in multiple compiles of the same content. This was necessary because the user may click something in the compact view, shrink the table (causing the compact view to accumulate more items that aren't yet compiled), then click an uncompiled element.

Code (simplified to show the essentials):

angular.module('myModule').directive('myDataTable', myDataTable);

function myDataTable($compile) {
    return {
        restrict: 'E',
        replace: true,
        templateUrl: 'my-data-table.directive.html',
        scope: {
            dtOptions: '=',
            dtColumnDefs: '=',
            dtColumns: '=',
            dtInstance: '='
        }, link: function (scope, element) {
            $(element).on('click', '.child *', function (event) {
                if (!!scope.$parent) {
                    var childElement = $(event.target).closest('.child')[0];

                    if (event.target.compiled !== true) {
                        $compile(angular.element(childElement).contents())(scope.$parent);
                        event.target.compiled = true;
                        $(event.target).click();
                    }
                }
            });
        }
    };
}

Template:

<table datatable=""
       dt-options="dtOptions"
       dt-column-defs="dtColumnDefs"
       dt-columns="dtColumns"
       dt-instance="dtInstance">
</table>

@Mouradif
Copy link

Mouradif commented Oct 14, 2016

I have been struggling with this issue for days before I decided that I'd let that problem for later when the rest of the project is finished. Now It's almost the last thing to fix in my project, and thank god I found this issue on GitHub.

@marcokorb your solution seems to be what I'm looking for, however, I get a parser error at
var data = api.( rowIndex, ':hidden' )...
I think you're missing something between api. and (rowIndex, ':hidden').

@rachellcarbone since you thanked him, did you manage to get his solution working ? How did you do it ?

@marcokorb
Copy link

Hi @Mouradif,

Check issue #552 and try using that way. I posted another way to do the same. I think it's better and more clear.

Hope can help.

@leahvi
Copy link

leahvi commented May 9, 2017

Hi,
I've tried the solutions above but nothing help...
This is my code:

 $scope.grid = {};
  $scope.grid.dtOptions = {
            responsive: {
                details: {
                    type: 'column',
                    target: -1
                }
            },
            columnDefs: [{

                orderable: false,
                targets: 'nosort'
            }],
            "sDom": 't',
            "aLengthMenu": [20]
            //colReorder: true,
        };

How can slove the problem ?
the ng-click not working when responsive the layout(screen)?

Thanks For Any Help!!

@hrefcl
Copy link

hrefcl commented Sep 23, 2021

.withOption('responsive', {
    details: {
        renderer: function (api, rowIdx, columns) {
            var data = $.map(columns, function (col, i) {
                return col.hidden ?
                    '<tr data-dt-row="' + col.rowIndex + '" data-dt-column="' + col.columnIndex + '">' +
                    '<td>' + col.title + ':' + '</td> ' +
                    '<td>' + col.data + '</td>' +
                    '</tr>' :
                    '';
            }).join('');

            var res = data ? $('<table/>').append(data) : false;
            if (res)
                $compile(angular.element(res).contents())($scope);
            return res;
        },
        type: 'column',
        target: 0
    }
})

Esa la solucion para el problema por si alguien todavia le sirve.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests