Link to home
Start Free TrialLog in
Avatar of Peter Kroman
Peter KromanFlag for Denmark

asked on

Avoiding empty rows in a table

Hi,

I have this code creating a row in a table if there is content in the corresponding db row:
<tr>   
               <td><? if (empty($row->Faldne_5)): ?>              
                <? else: ?>
                   <? echo $row->faldne?> 
               <? endif; ?> </td>

             </tr> 

Open in new window


The problem is, that if there is no content in the db for this row, it displays an empty row in the table, and that is exactly what I would avoid.

You can see an example here: https://kroweb.dk/gfdev/collecting_page2/soegedb/soegeDatabaser.php?sogn=Bjerning&amt=Haderslev in the table in the column to the left. Here are displayed two rows with content (which is correct) and one empty row (which actually also is correct) and here I need the empty row not to be displayed.

If anybody have some ideas on how to make that work I would be very happy :)
Avatar of Leonidas Dosas
Leonidas Dosas
Flag of Greece image

I show a JQuery solution.If you see the code checks every td and if its value is empty string thet it removes the tr.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script>
<title>HTML, CSS and JavaScript demo</title>
</head>
<body>
<!-- Start your code here -->

  <table>
    <tr><td>aaa</td></tr>
    <tr><td></td></tr>
    <tr><td>bbb</td></tr>
    <tr><td>ccc</td></tr>
    <tr><td></td></tr>
    <tr><td></td></tr>
     <tr><td>ddd</td></tr>
  </table>
  <script>
   $('td').each(function(){
  if($(this).text()===''){
    $(this).remove();
  }
});
  </script>
<!-- End your code here -->
</body>
</html>

Open in new window

Avatar of Peter Kroman

ASKER

Thansk Leonidas,

It works - but there is a little problem.

When I put in the js script type line after my datatables script line it works but then datatables is not working.
When I put it in the before the datatables line datatables is working but your solution is not working.

After:
<script type="text/javascript" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
        <script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script>

Open in new window


Before:
<script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script>
        <script type="text/javascript" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>

Open in new window

The problem with your code is, that it would need to know in advance whether all $row columns are empty.

So a solution should be using a variable to accumulate anything from <tr> to </tr> and another boolean $rowhasdata variable should keep track whether any case of non empty value happened and finally (before fetching the next row) echo the accumulated <tr>...</tr> HTML or not and therefore skip it. So having <tr> and </tr> and every <td> and </td> in the static non PHP part of your script already outputs it prematurely.

Bye, Olaf.
Create a function called renderRow()
Pass the current $row to it
In the function create a variable that determines the empty state of the row
Based on this render out the row
while($row = ...) {
   renderRow($row);
...
}
...
function renderRow($row)
{
  // Modify to test the conditions that mean the row is empty
  $rowEmpty = empty($row->faldne) && empty($row->someotherfield) && ....;

  // If row has content then HEREDOC it out
  if (!rowEmpty) {
   echo <<< ROW
    <tr>
       <td>{$row->faldne}</td>
    </tr>
ROW;
  }
}

Open in new window

EDIT: Fixed typo in ROW output
You might also fix your SQL to not return rows having all empty columns, eg WHERE col1+col2+col3+....<>=''. That might need taking care of data types and NULL.

Bye, Olaf.
Well - I have 208 columns and 2219 rows in the database table.
It is  - throughout the db-table- very different which columns has content in a given row and which is empty.
But there is content in some of the 208 columns in every of the 2219 rows.

@Olaf : So I don't think the SQL model is the right thing to do here ??

@Julian: I am not sure that I fully understand your suggestion. Do you mean that I should set check this up for all the 208 columns one by one, or is there an easier way to get around this? Could I ask you to fill out a little more of the code example you posted - especially the ...'s :)
Well, if every row has some data you can't leave out whole rows. And leaving out TDs means you shift columns, surely also not, what you'd want to do.

You can only skip whole rows if you only display part of all table columns and these group of columns is all empty. Your where clause would then reflect that, too. Just pick out the columns you also display, of course.

Bye, Olaf.
Yeah - I can't leave out any db-columns since there is content in some rows in all columns.

So it is actually in the HTML table alone, I want to control empty or not empty columns :)
You can't, just skipping <td></td> empty columns all further columns are shifted to the left. Do you want that? You can only remove all empty rows and you said there aren't any. Then I don't see any options.
Are you looking into removing grid lines? Notice, that'll make values appear as the value for two or more columns or multiple rows, even though they only belong into a single cell.

Therefore I don't see any sense in trying to reduce the HTML.

Only if you say just display 50 of the 208 columns and all 50 columns are empty for the row. Any of the other 158 columns in the database may have a value, but that's not listed anyway.

Bye, Olaf.
Just to clarify a little more.

I am doing a foreach loop through the array $data generated from the db query.

Looks something like this:
<?php foreach ($data as $row): ?>
            <tr> 
                <td><? if (empty($row->Nygaard_3)): ?> <!-- Do nothing --> 
                <? else: ?>
                   <? echo $row->nygaard?> 
               <? endif; ?> </td>
            </tr>
            
            <tr>   
               <td><? if (empty($row->Faldne_5)): ?>              
                <? else: ?>
                   <? echo $row->faldne?> 
               <? endif; ?> </td>

             </tr> 

            <tr>   
               <td><? if (empty($row->Oeders_10)): ?>
                <? else: ?>
                   <? echo $row->oeders?> 
               <? endif; ?> </td>

             </tr> 


        <?php endforeach; ?>

Open in new window


@Julian - How do I work your suggestion into that setup :)
I already thought you had a foreach of rows, that's logical. But OK, that shows you only display 3 of the 208 columns in this case. Then you can query

WHERE (...) AND `nygaard`+`faldne`+`oeders`<>''

Open in new window


Bye, Olaf.
ASKER CERTIFIED SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@Chris: Making every cell its own table row this way, that pushes everything not empty to the leftmost column. Oh I see, that's already the case in Peters original code.
Peter, why do you have multiple <tr></tr> pairs, each one is becoming it's own row, do you want that, is your table just a single column? The original code you posted only had one <tr></tr>.

Bye, Olaf.
Beautiful :)
Thanks Chris,

This works nicely.

Just one little question more.

When here is no data to display, it returns this english message: No data available in table

I have in the code set it up to return this danish message: Der er ingen resultater for denne søgning

Can you see why that is? I give you the full code (as it is right at this moment) here:

<?php require_once('lokale_data_SQL.php') ?>

<?php if (count($data)): ?>


    <div id= "soegLokale">

    <table id="LokaleTable" class="table">


        <!-- Top head -->
         <?php foreach ($data as $row): ?>
        <thead>
            <tr>
                <th class="sorting" aria-controls="LokaleTable"><? echo $row->sogn?> Sogn i <? echo $row->herred?> Herred, <?echo $row->amt?> Amt</th>          
            </tr>
        </thead>
        <?php endforeach; ?>


        <?php foreach ($data as $row): ?>
            <?php if ( ! empty($row->Nygaard_3)): ?>
            <tr> 
                <td><?php echo $row->nygaard ?></td>
            </tr>
            <?php endif; ?>

            
            <?php if ( ! empty($row->Faldne_5)): ?>
            <tr>   
                <td><?php echo $row->faldne ?></td>
            </tr>
            <?php endif; ?>

            
            <?php if ( ! empty($row->Oeders_10)): ?>
            <tr>   
                <td><?php echo $row->oeders ?></td>
            </tr>
            <?php endif; ?>

            
            <?php if ( ! empty($row->Skanderborg_12)): ?>
            <tr>   
                <td><?php echo $row->skanderborglex ?></td>
            </tr>
            <?php endif; ?>

            
            <?php if ( ! empty($row->FolketiMidten_13)): ?>
            <tr>   
                <td><?php echo $row->folketimidten ?></td>
            </tr>
            <?php endif; ?>
             
            
            <?php if ( ! empty($row->ejrs_14)): ?>
            <tr>   
                <td><?php echo $row->sejrssedler ?></td>
            </tr>
            <?php endif; ?>
             





        <?php endforeach; ?>




    </table>

 </div>    

<?php else: ?>

    <h6>Der er ingen resultater for denne søgning</h6>

<?php endif; ?>

Open in new window

That code so far works for you, really? Do you notice that you put each column of the sql result $row into its own row?

Bye, Olaf.
Yep Olaf,

That is just what I need here :)
Hey Peter,

If you're getting the English message, then it's possible that it's coming in as part of the $data variable. Therefore count($data) will return true and echo it out instead of failing the 'if' test and echoing out your Danish version.

For testing purposes, var_dump your $data variable before you count it and run the test with data you know should be empty.
Nice and simple :)

Thanks a lot Chris.
Just what I needed here.

About my last question, just forget about it. It is purely academic, because when I am finished building this page, there will be no situations where the any of the tables are totally empty.
No worries Peter - glad it's working :)
@Julian - How do I work your suggestion into that setup :)
Fairly simple - instead of using the function to output the data for a row simply pass the data item to the function and test it there.
A lot cleaner than a bunch of if statements in your code

while($row = ...) {
   renderRow($row->Nygaard_3);
   renderRow($row->Faldne_5);
...
}
...
function renderRow($data)
{
  if (!empty($data)) {
   echo <<< ROW
    <tr>
       <td>{$data}</td>
    </tr>
ROW;
  }
}

Open in new window

Yes, that's one the base principle of all programming, DRY: Don't repeat yourself. Functions can implement some test and result once and you just pass in the different values. I would keep all echoing of output on the topmost level and let a function only return its result value, but that's a matter of taste.

I just have to admit I misread your code to create one row per loop iteration, putting the three table fields in one row.

Bye, Olaf.
I would keep all echoing of output on the topmost level and let a function only return its result value
Except where the function exists solely to encapsulate output.
In this case, it is but I think more general. If I want to orchestrate output and collect HTML snippets from several modules I don't want them to autonomically output anything. I might take the table HTML from here and some other HTML from over there and put it together in some other way than it was generated chronologically.

Bye, Olaf.