2

1. Explaination:

I am creating an invoice page.

To populate the row data I am using a dropdown (i don't know a better way).

Now, I can successfully insert the data on the row but, when I select the dropdown value on any row, it changes the value of all the rows, when it should have changed only the selected one.

2. Question:

What am I doing wrong?

How can this be solved?

3. My frontend code:

 <table id="table1" border="0">
                <tr style="font-size:80%;">
                    <th>#</th>
                    <th style="width:50%;">Product</th>
                    <th style="width:5%;">qty</th>
                    <th style="width:5%;">price</th>
                    <th class="d-print-none">X</th>
                    @* <th class="d-print-none"></th>*@
                </tr>
                @{
                    int i = 0; 
                            foreach (var item in Model.PL)
                    {
                        <tr class="border-bottom">
                            <td class="tbl_id">1</td>
                            <td>
                                <select id="Products" asp-for="@Model.PL[@i].ProdId" class="form-control" type="text" name="data[@i][ProdId]" onchange="copyProd(this)" style="width:100%;"    >
                                  
                                    @foreach (var item in Model.PL)
                                    {
                                        <option    value="@item.ProdId"    
                                                qty="@qty"
                                            price="@Convert.ToInt32(item.price)">@item.name,   @Convert.ToInt32(item.price)</option>
                                    }

                                </select>

    <script>
            function copyProd(el) {

                let op = el.options[el.selectedIndex];
                let myvalue = el.value;
                let qty = op.getAttribute('qty');
                let price = op.getAttribute('price');

                //document.getElementById('xqtyId').value = qty;
                //document.getElementById('xpriceId').value = price;
                $("input[name='qty[@i]']").val(qty);
$("input[name='price[@i]']").val(price);
            }
        </script>
                            </td>
                        
@* *@ } i++; }    //JS class to price/delete rows in html table - https://coursesweb.net/javascript/ //receives table id function adRowsTable(id) { var table = document.getElementById(id); var me = this; if (document.getElementById(id)) { var row1 = table.rows[1].outerHTML;
                        //prices index-id in cols with class .tbl_id
                        function setIds() {
                            var tbl_id = document.querySelectorAll('#' + id + ' .tbl_id');
                            for (var i = 0; i < tbl_id.length; i++) tbl_id[i].innerHTML = i + 1;
                        }

                        //price row after clicked row; receives clicked button in row
                        me.priceRow = function (btn) {
                            btn ? btn.parentNode.parentNode.insertAdjacentHTML('afterend', row1) : table.insertAdjacentHTML('beforeend', row1);
                            setIds();
                        }

                        //delete clicked row; receives clicked button in row
                        me.delRow = function (btn) {
                            btn.parentNode.parentNode.outerHTML = '';
                            setIds();
                        }
                    }
                }

                //create object of adRowsTable(), pass the table id
                var ob_adRows = new adRowsTable('table1');
            </script>
           

4. The backend code:

 public async Task<IActionResult> OnGetAsync()
    {
        var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

        try
        {
            PL = await _context.Products.ToListAsync();

            var addrows = new List<InvoiceRows>()
        {
            new Products() { ProdId = 1, qty = 1, price = 0 },
            new Products() { ProdId = 1, qty = 1, price = 0 },
            new Products() { ProdId = 1, qty = 1, price = 0 },
        };

            PL = addrows;

            ViewData["ProdId"] = new SelectList(_context.Products, "ProdId", "Name");
        }
        catch (Exception e) { _ = e.ToString(); }

        return Page();
    }

    [BindProperty]
    public InvoiceRows InvoiceRow { get; set; } = default!;
    public IList<Products> PL { get; set; } = default!;
    
    public async Task<IActionResult> OnPostAsync(List<InvoiceRows> addRow)
    {

        _context.InvoiceRows.AddRange(addRow);

        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }
5
  • I included the "html" and posted the OnGet and the OnPost, backend code. Hope this helps to clarify things out. Commented Mar 4, 2023 at 16:04
  • it's hard to understand your dropdown, <option> doesn't contain the defintion for qty or price Commented Mar 6, 2023 at 5:35
  • Is it your purpoes: pass an 2D array which contains all properties of your all prodcuts and the drop down read text & id property form the array ,when you select one , dispalay the info in other inputs and remove the info related from the array,when you delete the row, add the info back to the array Commented Mar 6, 2023 at 5:40
  • @RuikaiFeng, i updated the dropdownlist, it seemed when i iniserted the code some parts were not visible. Commented Mar 6, 2023 at 12:15
  • @RuikaiFeng, i updated the dropdownlist, it seemed when i inserted the code some parts were not visible. I want to pass the data from the dropdown to the <input>. Each row will have its own values, which can be edited on need. I can already remove/delete rows. My problem is with the dropdown that indipendently from the row i select to insert data, it inserts/edits the data of the first row only. I want the dropdown to fill/edit the inputs of only the row i have selected. For example: If i select row nr.3, the dropdown will insert or edit the values only on row nr.3 Commented Mar 6, 2023 at 12:20

1 Answer 1

3

although you haven't shown the full table

it seems you tried with jquery selector incorrectly

$("input[name='qty[@i]']").val(qty);
$("input[name='price[@i]']").val(price);
        

You could try with parent/children to select the correct input instead of all the inputs

here's a minimal example may help you to modify the value of the input accord with the select in the same row:

<table>
    <tr>
        <th>Prop1</th>
        <th>Prop2</th>
        <th>Prop3</th>
    </tr>
    <tr>
        <td>
            <input value="P11"/>
        </td>
        <td>
            <input value="P12"/>
        </td>
        <td>
            <select >
                 <option >default</option>
                <option value="1" qq="qq1">OP1</option>
                <option value="2" qq="QWE1">OP2</option>
            </select>
        </td>
    </tr>
    <tr>
         <td>
            <input value="P21"/>
        </td>
        <td>
            <input  value="P22"/>
        </td>
        <td>
            <select >
                <option >default</option>
                <option value="1" qq="qq2">OP1</option>
                <option value="2" qq="QWE2">OP2</option>
            </select>
        </td>
    </tr>
</table>


<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script>
    $("select").change(function(){

        var selectValue = $(this).children('option:selected').attr("value");
        var qq=$(this).children('option:selected').attr("qq")
        $(this).parent().prev().children('input').val(selectValue)
        $(this).parent().prev().prev().children('input').val(qq)
       
       
    })
</script>

Result: enter image description here

Update:

$("select").change(function().....

The function was bound to the html element(selectlist) when the page was rendered(the selectlist you added haven't bound to the function ),if you want it work for a new row

try bind then function to document

$(document).on('change','select',function(){

        var selectValue = $(this).children('option:selected').attr("value");
        var qq=$(this).children('option:selected').attr("qq")
        $(this).parent().prev().children('input').val(selectValue)
        $(this).parent().prev().prev().children('input').val(qq)
    })

Result: enter image description here

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

6 Comments

Ruikai Feng, please define what a full table is. Maybe i did not understood your request, so i can add what you asked for. The code works great for static rows, but how do i have to edit it to work for dynamic rows? I tried : $(this).parent().prev().children("input[name='qty[@i]']").val(qty) $(this).parent().next().children("input[name='price[@i]']").val(price), but it edits only the first row. All the other rows remain blank/null.
the jquery codes would work for all select,firstly find the parent node(<td> ) of the current selectlist(which you selected an option ),then access the prev <td> node with .prev() and select the child node<input> with .children('input')
And what's your dynamic rows? like when you click a button ,it generate a new row contains the same input/dropdown?
I got it ,I'll deliever the solution to you tomorrow
Yes, on button click it adds a new row which contains the same input/dropdown. You can find the full code of inserting a new row, on page top.
|

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.