Jump to content


Caspio Ninja
  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by KlisaN137

  1. Hi @kpcollier Great spot by you, the proposed solution does not work if we have search form, and we are experiencing some strange behavior - hiding some other fields as you described it during consecutive search. The reason for this is because it appears that when 'Search' button is clicked, the code from footer is not executed only once, but a couple of times. In order to execute the code only once, when page is first reloaded, we can add an IF statement before the actual code, which will check how many columns are still there: <script> document.addEventListener('DataPageReady', function (event) { const check = document.querySelectorAll('table[data-cb-name="cbTable"] th'); /* Just set the number in IF below to the number of columns you have BEFORE hiding anything */ if(check.length===9){ // code goes here } }); </script> Additionally, I refactored whole code to be able to hide any number of columns without adding redundant code, just add or edit arguments in function deleting : <script> document.addEventListener('DataPageReady', function (event) { const check = document.querySelectorAll('table[data-cb-name="cbTable"] th'); if(check.length===9){ const deleting = (...args) =>{ let label, values for(let a of args){ label = document.querySelector(`table[data-cb-name="cbTable"] th:nth-of-type(${a})`); values = document.querySelectorAll(`table[data-cb-name="cbTable"] td:nth-of-type(${a})`); label.parentElement.removeChild(label); values.forEach(el => { el.parentElement.removeChild(el); }); } } /* In below function call, just put any number of column you want to hide, but in reverse order - from highest number to the lowest */ deleting(8,5); } }); </script>
  2. For the columns in a table in SQL, there is a maximum limit of 1024 columns in a table, I imagine same applies here.
  3. If you want to place Timestamp in Submission Form, you can use Virtual Field and set it in Advanced tab to Receive value or parameter like in the screenshot: The result is as follows: In the Report DataPages, you can just use Calculated field with value SysUTCDateTime() or SysDateTime()
  4. For the Submission Form, the code is a little bit different: <script> document.addEventListener('DataPageReady', () => { /* Select the input element of the Calculated Value */ document.querySelector('input[name="InsertRecordSum_Of_Values"]').addEventListener('change',()=>{ const replacing = (obj,whatToReplace,withWhatToReplace) => { obj.forEach(record => { const modified = record.textContent.replaceAll(whatToReplace, withWhatToReplace); record.textContent = modified; }); } const dollar = '$'; const euro = '€'; const pound = '£'; /* Select all Calculated Fields */ const calculated = document.querySelectorAll('.cbFormCalculatedField'); switch('[@authfield:Localization]'){ case 'Europe': replacing(calculated, dollar, euro); break; case 'Britain': replacing(calculated, dollar, pound); break; case 'USA': replacing(calculated, dollar, dollar); break; } }); }); </script> The result is the following when the user with European localization is logged:
  5. It is possible to change the currency sign dynamically, but only with a JavaScript solution. For the Report DataPage, set the fields formatting to US dollar ('$'). Then the following code should be put in the Footer of the DataPage: Note that if you are not using all the elements in the Report as described in the code, just delete the parts using that elements. <script> document.addEventListener('DataPageReady', () => { /* Declaring the function for replacing the specific text value in some array of HTML elements */ const replacing = (obj,whatToReplace,withWhatToReplace) => { obj.forEach(record => { const modified = record.textContent.replaceAll(whatToReplace, withWhatToReplace); record.textContent = modified; }); } /* Selecting all cells where we want to replace signs */ let table = document.querySelectorAll('.cbResultSetTableCellNumberDate'); // Table cells let htmlBlocks = document.querySelectorAll('.cbResultSetTableCell'); // HTML blocks inside the table let calculated = document.querySelectorAll('.cbResultSetCalculatedField'); // Calculated values in the table let sumAggregate = document.querySelectorAll('.cbResultSetTotalsDataCellNumberDate'); // Aggregates Total let aggregate = document.querySelectorAll('.cbResultSetGroup1LabelCellNumberDate'); // Aggregates in Group-level aggregations const dollar = '$'; const euro = '€'; const pound = '£'; /* Calling the Function 'replacing' for the declared elements, with arguments, based on the authentication field */ switch('[@authfield:Localization]'){ case 'Europe': replacing(table, dollar, euro); replacing(htmlBlocks, dollar, euro); replacing(aggregate, dollar, euro); replacing(sumAggregate, dollar, euro); replacing(calculated, dollar, euro); break; case 'Britain': replacing(table, dollar, pound); replacing(htmlBlocks, dollar, pound); replacing(aggregate, dollar, pound); replacing(sumAggregate, dollar, pound); replacing(calculated, dollar, pound); break; case 'USA': // Note that this case is redundant if using the dollar as default sign replacing(table, dollar, dollar); replacing(htmlBlocks, dollar, dollar); replacing(aggregate, dollar, dollar); replacing(sumAggregate, dollar, dollar); replacing(calculated, dollar, dollar); break; } }); </script> In the case you are using the "In Line Insert", then the part with declarations of variables "table" and "htmlBlocks" should be a replaced with the following code: /* Delete the variable "htmlBlocks" and replace the declaration of variable "table" with the code */ let tableParent = document.querySelectorAll('tr[data-cb-name="data"]') let table = []; tableParent.forEach(el => { let cells = el.querySelectorAll('.cbResultSetTableCellNumberDate'); table.push.apply(table, cells); let htmlBlocks = el.querySelectorAll('.cbResultSetTableCell'); table.push.apply(table, htmlBlocks); }); Also, delete the "replacing(htmlBlocks, currency, currency)" from Switch statement in this case. The resulting Report will look something like this if the user with European localization is logged in:
  6. Do you have some deployed DataPage on this, it would be helpful to see the whole thing?
  7. Alternately, if you want to show the parent field as "Display Only", but the DataPage doesn't permit using the Virtual Field element (Bulk Edit configuration, etc), set the field to "Text Field" and add the following code to the Footer of the Page (Bulk Edit Configuration): <script> if(typeof parentDisplayOnlyElement === "undefined"){ let parentDisplayOnlyElement = document.querySelector('input[name="BulkEditProductCategory"]'); // Select the input in the element you want to be just displayed parentDisplayOnlyElement.disabled = true; parentDisplayOnlyElement.style.border = 'none'; } </script>
  8. This hiding of the columns can also be achieved by using only JavaScript in the Footer: <script> document.addEventListener('DataPageReady', function (event) { let label = document.querySelector('table[data-cb-name="cbTable"] th:nth-of-type(8)'); // Select the label of eighth column let values = document.querySelectorAll('table[data-cb-name="cbTable"] td:nth-of-type(8)'); // Select all the values in the eighth column /* Removing the selected fields */ label.parentElement.removeChild(label) values.forEach(el => { el.parentElement.removeChild(el) }); /* If we want to remove additional columns */ label = document.querySelector('table[data-cb-name="cbTable"] th:nth-of-type(5)'); // Select the label of fifth column values = document.querySelectorAll('table[data-cb-name="cbTable"] td:nth-of-type(5)'); // Select all the values in the fifth column label.parentElement.removeChild(label) values.forEach(el => { el.parentElement.removeChild(el) }); }); </script> Main difference between this and approach with CSS is that here columns are entirely removed from the page, and not just hidden - in the CSS approach you could still find the elements if you inspect the page, and access the information in them, but in this JavaScript approach, they are completely removed from the page. Notice however, that in the above example we are first removing the column that comes after and work our way to the beginning. If we would also like to remove tenth column, we would put that code before the code for removal of the eighth.
  9. If we want to show some column in the Tabular Report just for the user who is also Administrator, but for the regular Users we want to hide it, below is the example (note that this is one Report DataPage - Tabular Report): Admin view can see the Agent Name column: User view can see the table without Agent Name column: In order to achieve this functionality, we need to add the following code to the DataPage Result page footer section: <script> document.addEventListener('DataPageReady', function (event) { /* If user is not Admin, we will remove the column */ if('[@authfield:Admin^]'==='No'){ /* We need to select Parent node of the Table Label and remove the desired child element (nth-child(2)) */ let agentLabelParent = document.querySelector('tr[data-cb-name="header"]'); let agentLabel = document.querySelector('tr[data-cb-name="header"] th:nth-child(2)'); agentLabelParent.removeChild(agentLabel); /* There can be multiple rows in the Tabular Report, so we need to select them all */ let agentNameParents = document.querySelectorAll('tr[data-cb-name="data"]'); /* Using the loop to pass through each row, and remove the entry (nth-child(2)) we don't need */ agentNameParents.forEach(parent => { let agentName = parent.querySelector('tr[data-cb-name="data"] td:nth-child(2)'); parent.removeChild(agentName); }); } }); </script>
  10. What you can do, if you want to use only one DataPage and show different navbars for users, is to have the "Users" table with the Yes/No field called Admin to check if user is Administrator, and to use Authentication based on the table. Then, make a Navbar in App Parameter like this: <p class="admin-navbar"> <a href="YOUR-URL">OPTION 1</a> <a href="YOUR-URL">OPTION 2</a> <a href="YOUR-URL">OPTION 3</a> <a href="YOUR-URL">OPTION 4 JUST FOR ADMIN</a> <a href="YOUR-URL">OPTION 5 JUST FOR ADMIN</a> </p> <p class="user-navbar"> <a href="YOUR-URL">OPTION 1</a> <a href="YOUR-URL">OPTION 2</a> <a href="YOUR-URL">OPTION 3</a> </p> We are making two Navbars, and we will filter out based on current user's field "Admin" which of these to show. So make a Footer in App Parameters with the following code: <script> document.addEventListener('DataPageReady', function (event) { /* We are selecting both navbars */ let navAdmin = document.querySelector('.admin-navbar'); let navUser = document.querySelector('.user-navbar'); /* We need to remove one only if both are present, this is to prevent console errors if reloading the page */ if(navAdmin && navUser){ let navParent = navAdmin.parentElement; '[@authfield:Admin^]'=== 'Yes' ? navParent.removeChild(navUser) : navParent.removeChild(navAdmin) } }); </script> Now just insert Navbar from App Parameters in DataPage Header section, and Footer from App Parameters into DataPage Footer section, and you'll see either admin-navbar or user-navbar based on the user authentication. Here is the result:
  • Create New...