Advanced Javascript - List Json data in HTML using loop and triggering an element change event, using Revealing Pattern

Viewed 82

I wrote a working example of a real problem that I'm trying to solve

I created an object simulating the json return I have from the database

I need:

  • list contracts and contract batchs
  • when entering the function, mark the last batch of the contract as selected in the drop-down list
  • when entering the function, display the invoices for the last batch only of the contract selected in the ul-invoices element.
  • load and display the respective invoices when changing the batch

Problems:

  • I cannot list invoices for the last batch of the selected contract
  • Although there is a function for onchange="getInvoices", I always getInvoices is not defined

Note:

  • When entering the page, I already have the information of the selected contract, in the case of the example, I left the contract with ID 1.
  • In the example I am using the in-attendance class to define the selected contract
  • I am using Revealing Pattern and I want to keep this pattern

<html>
    <label id="contracts"></label>
    <ul id="ul-invoices"></ul>
    
    <script>
        let lblContract = document.querySelector('#contracts');
        let UlInvoices = document.querySelector('#ul-invoices');
        
        let contractInAttendance = 1;
        
        const objectContract = {
            id: 1,
            nome: 'wagner',
            contracts: [{
                id: 1,
                contract: '123456',
                batches: [ {
                    id: 1,
                    contract_id: 1,
                    batch: '1',
                    invoices: [ {
                        value: 10,
                        batch_id: 1,
                    }]
                },
                {
                    id: 2,
                    contract_id: 1,
                    batch: '2',
                    invoices: [{
                        value: 10,
                        batch_id: 2,
                    }]
                }]
            },
            {
                id: 2,
                contract: '246789',
                batches: [ {
                    id: 3,
                    contract_id: 2,
                    batch: '1',
                    invoices: [ {
                        value: 20,
                        batch_id: 3,
                    }]
                }]
            }]
        }
        
        const revelling = (function() {
        
            function privateInit() {
                const contracts = objectContract.contracts;
                let contractFilteredById = contracts.filter(contract => contract.id === contractInAttendance);
                
                for (const contract of contracts) {
                    const selectedContract = contract.id === contractFilteredById[0].id ? 'in-attendance' : '';
                    
                    //let batchFilteredById = contract.batches.filter(batch => batch.id === batchInAttendance);
                
                    let htmlForBatchsOptions = contract.batches.map(batch => `<option value=${batch.id}>${batch.batch}</option>`).join('');
                    lblContract.innerHTML +=
                    `<div class="contract-${selectedContract}" style="display: flex;">
                        <div id="contract-${contract.contract}" data-contract="${contract.id}" class="loren">
                            <span>${contract.contract}</span>
                        </div>
                        <div class="ipsulum" style="margin-left: 5px;">
                            <select class="sel-batch" onchange="getInvoices(this)">
                                ${htmlForBatchsOptions}
                            </select>
                        </div>
                    </div>`;
                    
                    const batchOption = document.querySelector('select.sel-batch');
                    batchOption.value = 2;
                    
                    /!* create method for load invoices */
                    
                }
            }
            
            /!* Method fix for load invoices onchange sel-batch */
            function getInvoices(selectObject) {
                console.log('populate invoices element #ul-invoices');
            }
            
            return {
               init: privateInit()
            }
            
        })();
        revelling.init;
    </script>
    
</html>

1 Answers

The IIFE function in this pattern makes that method getInvoices private, so you can't add a handler this way, because it is trying to find a global method that doesn't exist.

You need to assign the event handler this way:

      lblContract.innerHTML +=
        `<div class="contract-${selectedContract}" style="display: flex;">
                        <div id="contract-${contract.contract}" data-contract="${contract.id}" class="loren">
                            <span>${contract.contract}</span>
                        </div>
                        <div class="ipsulum" style="margin-left: 5px;">
                            <select class="sel-batch">
                                ${htmlForBatchsOptions}
                            </select>
                        </div>
                    </div>`;

      const batchOption = lblContract.querySelector('select.sel-batch');
      // The event listener holds a reference to the inner function
      batchOption.addEventListener("change", getInvoices);
Related