0

I have a html/js code that takes data from a json and render it to html table. It has been working fine for a while. Recently the number of items being handled has greatly increased and can't afford to put data statically into html anymore. So I have changed the code in html and I'm now using data attributes, and a JS that loops through each item from the json file and writes it to the correct data attribute in html. It works. I have another JS file that scans through all td cells and if a condition is met the text in the cell turns red, or purple. Else it remains standard black. This used to work, but not anymore.

This is the new html code implemented:

`

<table id="table" align="center" render-area="reboot">
                <thead>
                    <tr>
                        <th class="text-center" data-tsorter="input-text">
                            Server Name
                            <img src='/icons/sort.png' width='20' height='20' style='display:inline;'>
                        </th>
                        <th class="text-center" data-tsorter="numeric">
                            Last Boot
                            <img src='/icons/sort.png' width='20' height='20' style='display:inline;'>
                        </th>
                    </tr>
                </thead>
                <tbody render-action="loop">
                    <tr render-data="json">
                        <td>{!Server Name!}</td>
                        <td>{!Last Boot!}</td>
                    </tr>
                </tbody>
            </table>

` and here below the JS that does not work anymore:

`

const today = new Date();
const todayMonth = (today.getMonth())+1;
const todayDay = today.getDate();
// Query all table cells in document
document.querySelectorAll('table td').forEach(function(td) {
  const srvDay = parseInt(td.innerHTML.split('/')[1]); // day
  if(Number.isInteger(srvDay)){
    const srvMonth = parseInt(td.innerHTML.split('/')[0]); //month
    // If date contained in td text before current date then apply red background style
    if(srvDay != todayDay || srvMonth != todayMonth){
        td.style.color = "red";
    }
  } 
  if((td.innerHTML.split(' ')[0]).includes('unreachable')){
        td.style.color = "purple";
  }
});

` if I examine that table td through the console, I get that the td html is !Last Boot! and that is why I believe the JS above does not work anymore. But if I look at the Elements console, I see that the DOM has all td correctly filled. In fact all works fine, except the JS above. The question is: how to manipulate data that is filled using data attributes? If I use a class for that td I get the same. Any hint?

UPDATE: I've found that when data is dynamically assigned it goes into an HTMLCollection, which I can now read as I found out which attribute to use to select the correct html element. In fact it contains the data I need, with the td cells filled in. But! don't know how to operate this htmlcollection. I've tried and I'm getting weird results. I've learnt that on htmlcollection foreach does not work. Either transform it into array with Array.from() or use for of loop. When I use any of the two I lose the data and again I get the placeholder {!Last Boot!}. This is how far I got:

`
function tdTextHandler(renderArea){
  const today = new Date();
  const todayMonth = (today.getMonth())+1;
  const todayDay = today.getDate();
  const newArr = document.querySelectorAll(`[render-area="${renderArea}"]`);
  newArr.forEach(function(e) {
  const newArr4 = (Array.from(e.children))[1].children
  
 console.log(newArr4);


for (item of newArr4) {
  console.log(item);
  const srvDay = parseInt(item.innerHTML.split('/')[1]); // day
  
  if(Number.isInteger(srvDay)){
    const srvMonth = parseInt(item.innerHTML.split('/')[0]); //month
    // If date contained in td text before current date then apply red background style
    if(srvDay != todayDay || srvMonth != todayMonth){
        item.style.color = "red";
    }
  } 
  if((item.innerHTML.split(' ')[0]).includes('unreachable')){
        item.style.color = "purple";
  }
};

`

the first console.log tells me that I have a htmlcollection and in the console I can see that its entries have the data. But the second console.log shows that the data is gone, although the structure is there and I'm back to the placeholder.

2 Answers 2

1

Solved. As the table is dynamically generated by another JS script, it is in that script (and in its loop) that the JS code above is to be placed.

Sign up to request clarification or add additional context in comments.

Comments

0

if you have something like:

<div data-myAttribute="1"></div>
<div data-myAttribute="2"></div>
...

you select them :

const els = document.querySelectAll('div[data-myAttribute');
els.forEach(e => {
    ...
})

7 Comments

same problem. I did: document.querySelectorAll('table td[data-date]').forEach...etc.. although I can select successfully the elements, I still get in the console: innerHTML: "{!Last Boot!}" innerText: "{!Last Boot!}" instead of the actual values.
because that's what you have in last td. Your for each loop is looping through td in your html, you have 2 td, last one is last boot. You are saying in your text you are looping through json, it's not the case in your loop
Step 1. Parse json file > loop through data and assign it to data attribute. Done, it works. Step 2. Loop through the td data available for condition matching. This is done with document.querySelectorAll('table td').forEach(function(td) {.....etc. So it is the case. I'm trying to figure out which exact data attribute in the html to use for selecting. In a static table my code would work. But in tables with dinamically assigned data things change. I'm trying to understand that.
ok I understand. Did you check content of your td, just before running your function?
yes, it is rendered correctly on page. The html table is correctly displayed with data. In Elements Console I can view the td correctly filled in. But the selection "table td" that I use in JS does not catch that. Instead it catches the data attribute placeholder
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.