Add link to cell using dynamic columns from nested JSON data.

Add link to cell using dynamic columns from nested JSON data.

jamesxjamesx Posts: 5Questions: 1Answers: 0

I am trying to get a hyperlink in the cells using dynamic columns from nested data. You can see in the example data below that I have 3 columns that need to be hyperlinks using the nested data that have "type": "url". Is this possible? I could of course use non-nested data and have separate url and link text entries but I'm not sure how I would then target those columns dynamically? Thanks.

Here is my current jQuery:

var data,
    tableName = "#example",
    columns,
    str,
    jqxhr = $.ajax("data/real-data.json")
      .done(function () {
        data = JSON.parse(jqxhr.responseText);

        // Iterate each column and print table headers for Datatables
        $.each(data.columns, function (k, colObj) {
          str = "<th>" + colObj.name + "</th>";
          $(str).appendTo(tableName + ">thead>tr");
        });

        var table = $(tableName).dataTable({
          data: data.data,
          columns: data.columns,
          orderCellsTop: true,
          fixedHeader: true,
          pageLength: 100,
          responsive: {
            details: {
              type: "column",
            },
          },
          order: [1, "asc"],
          columnDefs: [
            {
              className: "dtr-control",
              orderable: false,
              targets: 0,
            },
          ],
        });
      });

Here is some example data to show the current structure:

"data": [
    {
      "quant_qual": "Quantitative",
      "specificity": "Event",
      "val_meth": {
        "text": "LinkA1",
        "type": "url",
        "link": "https://google.co.uk"
      },
      "meth_val_trail_rep": {
        "text": "LinkA2",
        "type": "url",
        "link": "https://google.co.uk"
      },
      "dna_ex_app": {
        "text": "LinkA3",
        "type": "url",
        "link": "https://google.co.uk"
      }
    },

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 20,277Questions: 26Answers: 4,766

    Use columns.data to define the columns. Use columns.render to build the url. See the example in the docs. You would use something like data.type to get to the URL. See this example of data rendering.

    Kevin

  • jamesxjamesx Posts: 5Questions: 1Answers: 0

    Many thanks for the quick response Kevin.

    I am unable to define the columns manually, they need to be created dynamically from the data which I believe is where the issue lies. How would I tap into the dynamically loaded columns using the columns.render as you have suggested? Thanks

  • kthorngrenkthorngren Posts: 20,277Questions: 26Answers: 4,766

    I would look at adding columns.render to those columns while you are dynamically building them.

    Kevin

  • kthorngrenkthorngren Posts: 20,277Questions: 26Answers: 4,766

    Looks like you are populating the DOM with the header. You could possibly use columnDefs to define the columns.render function, assuming its the same for all columns. You would set a classname for the header defining the columns to render the url. Set the columnDefs.targets to use that classname.

    Kevin

  • jamesxjamesx Posts: 5Questions: 1Answers: 0

    Fantastic thanks Kevin, that seems like a good approach. Is there a way of making the "targets" target dynamic class names as such? I have now successfully added a class name to each th:

            $.each(data.columns, function (k, colObj) {
              str = `<th class="${colObj.data}">${colObj.name}</th>`;
              $(str).appendTo(tableName + ">thead>tr");
            });
    

    How could I then hook it up with the targets dynamically so the target class matches the dynamic link? This is the manual example I have:

                {
                  targets: -1,
                  render: function (data, type, row, meta) {
                    if (type === "display") {
                      data = `<a href="${row.dna_ex_app.link}" target="_blank">${row.dna_ex_app.value}</a>`;
                    }
    
                    return data;
                  },
                },
    
  • jamesxjamesx Posts: 5Questions: 1Answers: 0

    I should given you this one which works but is still not dynamic:

                    {
                      targets: "ctrl_samp",
                      render: function (data, type, row, meta) {
                        if (type === "display") {
                          data = `<a href="${row.ctrl_samp.link}" target="_blank">${row.ctrl_samp.value}</a>`;
                        }
    
                        return data;
                      },
                    },
    

    I think I will also need to do a check if it has the nested "type": "url" somehow?

    Thanks

  • kthorngrenkthorngren Posts: 20,277Questions: 26Answers: 4,766

    I think I will also need to do a check if it has the nested "type": "url" somehow?

    I suspect you will.

    Kevin

  • jamesxjamesx Posts: 5Questions: 1Answers: 0

    Thanks for your help Kevin, I have managed to get this working but I'm targeting the columns in a hacky way:

            $.each(data.columns, function (k, colObj) {
              str = "<th>" + colObj.name + "</th>";
              $(str).appendTo(tableName + ">thead>tr");
              colObj.render = function (data, type, row, meta) {
                if (type === "display" && data == "[object Object]") {
                  return '<a href="' + data.link + '">' + data.value + "</a>";
                } else {
                  return data;
                }
              };
            });
    

    ...instead of && data == "[object Object]" is there a way of checking for "type": "url" within the data?

  • kthorngrenkthorngren Posts: 20,277Questions: 26Answers: 4,766
    Answer ✓

    I'd use hasOwnProperty() to check. See this tutorial for Javascript ways to check an object for certain properties.

    Kevin

Sign In or Register to comment.