0

Good evening all, I know this is using an older stack; however, it is my starting spot to get something working before moving to a different stack with more features.

I have a Node.JS application running ejs templates, and on one of those pages is a datatable that has revealable "child" rows. In those child rows are a couple of buttons, and one opens a model to display a form that is going to be populated from a JSON object in data.form_data.

I have my modal html being pulled in via:

<%- include("../dataView/viewFullformModal") %> 

All of my data is available in the "data" variable. It is rendering data.formType, data.customer_name, data.dateReceived, and others; HOWEVER, I am needing to include another ejs file with the specific layout for the various forms. So I figured the easiest way was either an "if" or a "switch" statement and here is where I am having issues: the "data" variable is accessible to the <% if statement.

My if statement is as follows:

<% if ( data.formType === 'Schedule Consultation Form') { %>
    '<p> yes </p>' +
<% } else { %>
    console.log(data.formType) +
<% } %>

This is returning "undefined"; however right before this I have the following code that is working:

'formType: ' + formType + '</br>' +

This returns: "formType: undefined"

And, before this code i have the following that is NOT working:

<% data.formType %>

This returns: "NaN"

This is one of two problems, but it is the major problem right now.

Here is my main template file being loaded as the body: dataTable.ejs

<div class="card">
    <div class="card-header">Submitted Form Data</div>
    <div class="card-body">
        <div class="table-responsive">
            <table id="customer_data" class="table table-bordered">
                <thead>
                    <tr>
                        <th></th>
                        <th>Date Received</th>
                        <th>Form Type</th>
                        <th>Customer Name</th>
                        <th>Email</th>
                        <th>Form Status</th>
                        <th>Reviewed By</th>
                    </tr>
                </thead>
                <tfoot>
                    <tr>
                        <th></th>
                        <th>Date Received</th>
                        <th>Form Type</th>
                        <th>Customer Name</th>
                        <th>Email</th>
                        <th>Form Status</th>
                        <th>Reviewed By</th>
                    </tr>
                </tfoot>
                <tbody></tbody>
            </table>

        </div>
    </div>
</div>

<script>
    $(document).ready(function(){
        function format ( data ) {
            // `d` is the original data object for the row
            console.log ( data.form_data);
            console.log ( data.formType);
            let formType = data.formType;
            return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
                <%- include("../dataViews/childRowHeader") %>
                <%- include("../dataViews/childRowDetails") %>
                <%- include("../dataViews/childRowFormData") %>
                // include Modals
                <%- include("../dataViews/viewFullFormModal") %>
                <%- include("../dataViews/addNotesModal") %>
                <%- include("../dataViews/markReviewedNotesModal") %>

            '</table>';
        }

        //let dataTable = $('#customer_data').DataTable({
        let dataTable = new DataTable($('#customer_data'), {
            'processing' : true,
            'serverSide' : true,
            'serverMethod' : 'get',
            'ajax' : {
                'url' : '/get_data'
            },
            'aaSorting' : [],
            'columns' : [
                {
                    className: 'dt-control',
                    orderable: false,
                    data: null,
                    defaultContent: ''
                },
                { data : 'dateReceived' },
                { data : 'formType' },
                { data : 'customer_name' },
                { data : 'customer_email' },
                { data : 'form_status' },
                { data : 'reviewed_by' }
            ]
        });

        dataTable.on('click', 'td.dt-control', function (e) {
            let tr = e.target.closest('tr');
            let row = dataTable.row(tr);

            if (row.child.isShown()) {
                // This row is already open - close it
                row.child.hide();
            }
            else {
                // Open this row
                row.child(format(row.data())).show();
            }
        });

    });

</script>
<script src='../../assets/scripts/modalScript.js' type="application/json">  </script>

Here is the included viewFullFormModal.ejs

'<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">'+
    '<div class="modal-dialog modal-dialog modal-xl" role="document">'+
        '<div class="modal-content">'+
            '<div class="modal-header">'+
                '<h5 class="modal-title" id="exampleModalLabel"><strong>' + data.formType + '</strong> submitted by: ' + data.customer_name + ' on ' + data.dateReceived + '</h5>'+
                '<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">'+
                    '<span aria-hidden="true">&times;</span>'+
                '</button>'+
            '</div>'+
            '<div class="modal-body">'+
                'formType: ' + data.formType + '</br>' +
                'formType: ' + formType + '</br>' +

                <% data.formType %> + '</br>' +
                <% if ( data.formType === 'Schedule Consultation Form') { %>
                    '<p> yes </p>' +
                <% } else { %>
                    '<br>' +
                    console.log(data.formType) +
                <% } %>

            '</div>' +
            '<div class="modal-footer">'+
                '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>'+
                '</div>'+
            '</div>'+
        ' </div>'+
    '</div>'+
'</div>'+

I can remove the whole "if" statement and include the following file (scheduleConsultationFormLayout.ejs) and it returns the data correctly:

'<p>' +
    'First Name: ' + data.form_data[4.3] + '</br>' +
    'Last Name: ' + data.form_data[4.6] +
'</p>' +
2
  • Uh, don't mix HTML with JavaScript code with HTML in strings in JavaScript code like that. Commented Sep 6, 2024 at 5:15
  • Sorry, I was following a tutorial and that is what was said to do. Thanks for the note though. Commented Sep 8, 2024 at 3:18

1 Answer 1

0

Sadly there is not a lot of documentation regarding EJS, so it can be difficult to grasp certain aspects of it.

About your problem, that formType is undefined or NaN.

<% if ( data.formType === 'Schedule Consultation Form') { %>
    '<p> yes </p>' +
<% } else { %>
    console.log(data.formType) +
<% } %>

The issue in this snippet comes down the EJS tags. Since viewFullFormModal.ejs is essentially a HTML file (normal case), it does not know what to with the console.log(...). It is neither inside an EJS tags nor inside a script so the HTML parser only sees it as text. This matter can be solved by removing the tags that exclude the console.log(...), so the EJS parser can run the console.log(...).
Note: This will be logged in the console of the server, since it still is server-side rendering

<% if ( data.formType === 'Schedule Consultation Form') { %>
    '<p> yes </p>' +
<% } else {
    console.log(data.formType)
} %>

Something similar is happening in the other two cases:

'formType: ' + formType + '</br>' +

Same as before, the HTML parser does not know formType and thus returns undefined, this will work if writter as

'formType: ' + <%= formType %> + '</br>' +

<% data.formType %>

Interestingly the solution to this can be found in the few lines of documentation on the offical docs.

<% is a "scriplet" tag, meaning it is used to execute things like if statements, loops, etc..
<%= is a "output" tag, meaning that it is used to output strings

So to output the formType you would need to write it as

<%= data.formType %>

One thing that I find weird how you've done it, is viewFullFormModal.ejs. Why wrap each line with an apostrophe? You can write the ejs file as usual, then, when you include the file, using <%- it will return the output as string. In most, if not every, IDEs this will be marked as an error, even thought it works. To get rid of the error, just wrap the whole EJS part in a string delimiter, so either " quotation mark, ' apostrophe or ` gravis. I prefer the gravis, as quotation marks and apostrophes are already likely to be used inside the file, so it would mess up the delimiters of the string.

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

4 Comments

"It is neither inside an EJS tags nor inside a script" - actually it is: <script> … function format (data) { … return … + <%- include("../dataViews/viewFullFormModal") %>. But yes, this is still totally weird
@Bergi The string that is returned from the include() is inside the script tag yes, the string also contains the console.log(data.formType); yes, but in the end what is returned from the include() is just a string. It is not parsed as javascript, but is a plain string, which is why I said I find it very weird that you wrote every line in viewFullFormModal.ejs as string. Even if you write it as normal HTML markup, the result from the include() is still just a string.
@greenSaiko, so I did this based on a tutorial, and that is what they had me use was the apostrophes around everything, and when I took them all out it died on me and gave me errors. I will look at going back and trying this. I ended up using things to build classes and id and used CSS to hide/show when needed. Not the best case, but I couldn't get it to work any other way. The only issue I'm running into this way is access the iTotalRecords that are a part of the res.json(output)
Interestingly enough <% %> did not work HOWEVER I did just spend time and go through and update all the code and attempted to use nothing; however, that did not work so I ended up going with the ` backtick. That worked, and now I can use template literals ${data.form_type} and it works for data FROM the res.json(output). I'm about to start playing with other things now too. EDIT: Looks like I can now use <% %> and pull in variable from outside the EJS file now!

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.