Extend code to multiple Datatables not in the same file

Extend code to multiple Datatables not in the same file

silkspinsilkspin Posts: 141Questions: 32Answers: 5

What I was attempting is something similar to jQuery.extend() where I can set defaults for multiple Datatables. The setting defaults page shows how to extend, but that looks like it's only for multiple Datatables in the same file. What I'm looking to do is something similar to how I use include.php to reuse code in different locations.

The target would be different on each DT. I'm assuming I would need to opt for targets: '_all' in this case because variables wouldn't work? The code below shows an edited down version of what I'd like to use globally. Is this possible or would I just need to repeat this in each standalone DT? Thanks.

columnDefs: [
    {
        targets: [1],
        render: function(data, type, row) {
            var d = $.fn.dataTable.render.text().display(data);
            d = d
            .replace(/link1/g, '<a href="' + row["URL1"] + '" target="_blank">' + row["URLtext1"] + '</a>')
            .replace(/link2/g, '<a href="' + row["URL2"] + '" target="_blank">' + row["URLtext2"] + '</a>')
        }
    },
],

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    Can you put your defaults into a .js file that you include in the required pages?

    Kevin

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    Hi @kthorngren. I did attempt to do this in a .js I use for global functions and global variables, but it didn't work. Maybe I didn't approach it the correct way though. Do you have an example?

    I tried to add the .replace(/link1/g etc. to a global variable d = d + linkvar; but that adds it as text to the output after the DT is built rather than run it as the replace method in columnDefs.

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    edited October 2021

    I did attempt to do this in a .js I use for global functions and global variables, but it didn't work

    You need to follow Javascript scoping rules. Do you get errors in the console? Loading JS from a file shouldn't be any different than including the code directly in your file.

    Do you have an example?

    Here is a simple example. I created a github repo to be used as a CDN:
    http://live.datatables.net/fimabife/1/edit

    The JS include file contains just this code:

    $.extend( $.fn.dataTable.defaults, {
      columnDefs: [
        {
          targets: 1,
          render: function (data, type, row) {
            return data + myGlobal;
          }
        }
      ]
    } );
    

    You will see ' zip' or whatever text you assign to the global variable myGlobal is appended to the Position column.

    The target would be different on each DT. I'm assuming I would need to opt for targets: '_all' in this case because variables wouldn't work?

    The columnDefs.targets lists all the options. One that might work is to use a classname. See this example using classname:
    http://live.datatables.net/cuwuvemu/2/edit

    I tried to add the .replace(/link1/g etc. to a global variable d = d + linkvar; but that adds it as text

    Have no idea. Can you create a test case showing the issue?

    Looking at the code snippet above it doesn't look like you are returning anything in columns.render. You need to return the data you want to display.

    Kevin

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    Hi @kthorngren. Your classname example is a great way for targeting multiple columns that might be different in each DT instance. I'll be able to give each <th> a class so thanks for that.

    I've followed your other example where you use the external .js and the $.extend(). Although that works for adding text content to a DT it's not what I need in my case. The .replace method in my original example works fine in my dev version. The example I gave was for when the data contains "link1", it is replaced by an actual link that is constructed from 2 columns. One containing the URL and the other the link text. I tried adding the code in a global variable but it isn't viewed as code when the .js is run. I think the best way to explain this is by using the data in the test case.

    So, based on your example and what I currently use within the main DT .js file, I expect the external .js to be something like...

    $.extend( $.fn.dataTable.defaults, {
      columnDefs: [
            {
                targets: [1],
                render: function(data, type, row) {
                    var d = $.fn.dataTable.render.text().display(data);
                    d = d
                    .replace(/Technical/g, 'Tech.')
                    .replace(/System/g, 'Sys.')
                    return d;
                }
            }
      ]
    } );
    

    This should replace all instances of Technical with Tech. and System with Sys. in column 1. When I tried to run this on my local dev the console said targets is undefined. If I remove the external file and paste the code above back into the columnDefs then it works fine again. Hopefully I've explained it better this time. Sorry for not being clear and not being able to put a test case together with what I'm trying to achieve because it isn't straightforward, but if it can be done it's a great way of being able to change settings in one place that affect multiple DTs.

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    I copied your code into a new file in my github repo and loaded it here:
    http://live.datatables.net/zozasapo/1/edit

    It works. Its your turn to provide an example of the non-working solution so we can help debug :smile:

    Kevin

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    Thank you for proving it does work @kthorngren. After a lot of trial and error I have managed to replace the contents of a column with an external .js, but unfortunately this might not function as I need.

    I found that the only way I could extend the columnDefs was to remove the existing columnDefs in the main DT .js. I assumed $.extend added to an existing columnsDefs. If this isn't correct then I'm guessing I won't be able to reuse code globally? Each DT has it's own requirements in columnDefs but I also need to merge in global requirements.

    I've created an example using your base test. I've changed the colour of the text in the "Name" column to red... http://live.datatables.net/zozasapo/3/edit

    But, now the replacing of words in the "Position" column doesn't happen. If the code below is removed then the words are replaced.

        columnDefs: [
          { className: "red", targets: [ 0 ] }
        ],
    
  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    edited October 2021

    The behavior you describe is documented in the options docs. Any option in the Datatables initialization will override the defaults. The options aren't merged.

    One way you can merge them is to have a variable containing the default options and another containing the specific requirements. Then merge the two variables to be used as the columnsDefs option in the init code.

    Kevin

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    Thank you for confirming what I was beginning to think Kevin! I've tried to use variables, but that isn't straightforward with so many columnDefs options and throwing up more errors in the console. I'm going to abandon this idea and stick with manually updating each file when I need too. Thank you for all your help.

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    Hi @kthorngren. I've been trying your suggestion about merging 2 variables because I don't like to give up! :smile: After a lot of Googling I'm stuck. It's a JS problem I'm having rather than DT. It partly works when each file only contains one property, but when I have 2 or more in one variable it breaks. I know this is down to there being multiple braces, and I have tried many combinations like wrapping in other braces/brackets, but I've been unsuccessful. Do you know of a way to include a few properties in one variable? The code below does work if the property {targets: [1], searchable: false} is removed.

    // **** I NEED THIS CODE IN THE FIRST .JS FILE
    
    let js1 = 
        {
            targets: [1],
            orderable: false
        },
        {
            targets: [1],
            searchable: false
        }
    
    // **** I NEED THIS CODE IN THE SECOND .JS FILE
    
    let js2 = 
    {
        targets: [1],
        render: function(data, type, row) {
            var d = $.fn.dataTable.render.text().display(data);
            d = d
            .replace(/Technical/g, 'Tech.');
            return d;
        }
    }
    
    // **** THE THIRD .JS FILE NEEDS TO BRING THE 2 .JS FILES ABOVE TOGETHER
    // **** USING EXTEND, THIS IS PUSHED THROUGH TO THE INITIALISATION .JS
    
    $.extend( $.fn.dataTable.defaults, {
          columnDefs: [
                js1,
                js2
            ]
    } );
    
  • tangerinetangerine Posts: 3,342Questions: 35Answers: 394
    let js1 =
        {
            targets: [1],
            orderable: false
        },
        {
            targets: [1],
            searchable: false
        }
    

    You can't have two "targets" definitions. The second will override the first.

            targets: [1],
            orderable: false,
            searchable: false
    
  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    Answer ✓

    js1 needs to be an array of objects. Just for consistency js2 should be an array of objects (well just one object). Then combine the arrays using one of the techniques demonstrated here.. Something like this:
    http://live.datatables.net/xapoqoqi/1/edit

    Kevin

  • silkspinsilkspin Posts: 141Questions: 32Answers: 5

    That is amazing @kthorngren! I came close when I tried adding the [ ] but I didn't see anything about the 3 dots prefix needed to pull in the array. This is now a really useful feature and will prevent the need to change multiple files. A global set of columnDefs will save time and cut down on config errors. Thank you very much.

Sign In or Register to comment.