Forum Stats

  • 3,838,817 Users
  • 2,262,400 Discussions
  • 7,900,761 Comments

Discussions

Display 'No data to display' in table

User_JV7C1
User_JV7C1 Member Posts: 60 Employee
edited Feb 13, 2018 2:30AM in Oracle JET

I am on JET version 3.2 and i am using a html table (not ojTable) to display the data in an array. I preferred using html table, as my requirement is to render the column headers as link, with a menu to be displayed on the click of the same, update the header with the item selected from the menu. This was easier to be implemented with a html table, so i went with it. Now my question is how do i display the text 'No data to display' when there are no rows in the array? The array will get updated everytime the user clciks on the header and chooses a different value.

I tried the following approach:

<table>

                                                <thead>

                                                    <tr>

                                                        <th style="text-align: center;">

                                                          //code to display the column header as link

                                                        </th>

                                                        <th style="text-align: center;">

                                                            //code to display the column header as link

                                                        </th>

                                                    </tr>

                                                </thead>

                                                  //displayData is a knockout observable maintained in the view model

                                                  //displayData is set to 'true' if the length of 'arrayData' is > 0, else its set to false

                                                <div data-bind="if: displayData ">

                                                <tbody data-bind="foreach: arrayData">

                                                    <tr>

                                                        <td style="text-align: center;"  data-bind="text: sourceData"></td>

                                                        <td style="text-align: center;"  data-bind="text: targetData"></td>

                                                    </tr>

                                                </tbody>

                                                </div>

                                                <div data-bind="if: displayData ">

                                                <tbody >

                                                    <tr>

                                                        <td style="text-align: center;"  >No data to display</td>

                                                        <td style="text-align: center;"  ></td>

                                                    </tr>

                                                </tbody>

                                                </div>

                                            </table>

View Model Code:

self.arrayData = ko.observableArray();

     self.arrayDataLength = ko.computed(function() {

return self.arrayData.length ;

});

self.displayData = ko.computed(function() {

if (self.arrayData.length > 0) return true;

else

return false;

});

This approach is currently not working completely, in the sense, initially when the page is loaded and there is no data in the array, only the 'No data to display' is displayed. But once i update the headers (by clicking on the header link and selecting a different item), the array gets populated, now the newly added rows into the array are dispalyed in the table, but the 'No data to display' text is not getting hidden, though i am controlling the display with a flag which is a knockout observable. Can someone please point out why?

I didnt want to have two tables, one for showing data and other for no data , as the header section is going to be the same and its not a hardcoded header, hence it would make the code redundant. Can someone please advise if this is a right approach or not?

Tagged:
User_JV7C1

Best Answer

  • Andrew Bennett
    Andrew Bennett Member Posts: 240 Silver Badge
    edited Feb 12, 2018 3:54PM Answer ✓

    Hi,

    If you replace the table block of code with this. It's now making use of the   <!-- ko if:  syntax, that will allow you to have the tbody tag without a div tag wrapped around it

    <table>      <thead>        <tr>          <th style="text-align: center;">            Heading1          </th>          <th style="text-align: center;">            Heading2          </th>        </tr>      </thead>      <!-- ko if: displayData -->      <tbody data-bind="foreach: arrayData">        <tr>          <td style="text-align: center;" data-bind="text: 'Content1'"></td>          <td style="text-align: center;" data-bind="text: 'Content2'"></td>        </tr>      </tbody>      <!-- /ko -->      <!-- ko ifnot: displayData -->      <tbody>        <tr>          <td style="text-align: center;">No data to display</td>          <td style="text-align: center;"></td>        </tr>      </tbody>      <!-- /ko --></table>

    Then also change your computed observable to the following - Have the self.arrayData.length changed to self.arrayData().length, this way the observable will calculate itself again when a new item it added / removed.

    When you do self.arrayData that returns the observable function rather than the actual array items, and when you do .length on that it results in a length of 0. This value was never changing, hence this function never ran again when you added items.

    When you do self.arrayData() that returns the actual array items, so you can do .length on there. A rule of thumb, when you are using computed functions and the result of that is dependent on a different observable, always use the (), that will reference it properly, and make sure that the computed function re-evaluates output when the observable it's using is updated

    self.displayData = ko.computed(function () {        if (self.arrayData().length > 0) {          return true;        }        else {           return false;        }});

    Cheers,

    Andy

    User_JV7C1User_JV7C1

Answers

  • Andrew Bennett
    Andrew Bennett Member Posts: 240 Silver Badge
    edited Feb 12, 2018 3:54PM Answer ✓

    Hi,

    If you replace the table block of code with this. It's now making use of the   <!-- ko if:  syntax, that will allow you to have the tbody tag without a div tag wrapped around it

    <table>      <thead>        <tr>          <th style="text-align: center;">            Heading1          </th>          <th style="text-align: center;">            Heading2          </th>        </tr>      </thead>      <!-- ko if: displayData -->      <tbody data-bind="foreach: arrayData">        <tr>          <td style="text-align: center;" data-bind="text: 'Content1'"></td>          <td style="text-align: center;" data-bind="text: 'Content2'"></td>        </tr>      </tbody>      <!-- /ko -->      <!-- ko ifnot: displayData -->      <tbody>        <tr>          <td style="text-align: center;">No data to display</td>          <td style="text-align: center;"></td>        </tr>      </tbody>      <!-- /ko --></table>

    Then also change your computed observable to the following - Have the self.arrayData.length changed to self.arrayData().length, this way the observable will calculate itself again when a new item it added / removed.

    When you do self.arrayData that returns the observable function rather than the actual array items, and when you do .length on that it results in a length of 0. This value was never changing, hence this function never ran again when you added items.

    When you do self.arrayData() that returns the actual array items, so you can do .length on there. A rule of thumb, when you are using computed functions and the result of that is dependent on a different observable, always use the (), that will reference it properly, and make sure that the computed function re-evaluates output when the observable it's using is updated

    self.displayData = ko.computed(function () {        if (self.arrayData().length > 0) {          return true;        }        else {           return false;        }});

    Cheers,

    Andy

    User_JV7C1User_JV7C1
  • User_JV7C1
    User_JV7C1 Member Posts: 60 Employee
    edited Feb 13, 2018 2:30AM

    That worked. Thanks for the response.