skip to Main Content

I have a field called price in the plans table.

public function up(): void
{
    Schema::create('plans', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained()->cascadeOnDelete();
        $table->foreignId('doctor_id')->constrained()->cascadeOnDelete();
        $table->foreignId('type_id')->constrained()->cascadeOnDelete();
        $table->string('price')->nullable();
        $table->string('description')->nullable();
        $table->timestamps();
    });
}

And I have two tags, select option and span.

<select class="form-select" id="plan_id" name="plan_id">
    @foreach($plans as $plan)
        <option value="{{ $plan->id }}">{{ $plan->title }}</option>
    @endforeach
</select>

<span id="totalPrice">&nbsp;</span>

I want to display the totalPrice id price after the select option is selected. Which shows undefined.

<script>
    document.addEventListener('DOMContentLoaded', function() {
        var planSelect = document.getElementById('plan_id');
        var timeSelect = document.getElementById('time_id');
        var priceTotal = document.getElementById('totalPrice');
        planSelect.addEventListener('change', function() {
            var planId = this.value;
            var xhr = new XMLHttpRequest();
            xhr.open('GET', '{{ route('findIDTime') }}?id=' + planId, true);
            xhr.onload = function() {
                if (xhr.status === 200) {
                    var data = JSON.parse(xhr.responseText);
                    console.log(data);
                    timeSelect.innerHTML = '';
                    for (var i = 0; i < data.length; i++) {
                        var option = document.createElement('option');
                        option.value = data[i].id;
                        if (data[i].direction === 1) {
                            option.textContent = data[i].start_time + ' صبح';
                        } else {
                            option.textContent = data[i].start_time + ' عصر';
                        }
                        timeSelect.appendChild(option);
                        priceTotal.innerText = data[i].price;
                    }
                } else {
                    console.log('Error: ' + xhr.status);
                }
            };
            xhr.onerror = function() {
                console.log('Request failed');
            };
            xhr.send();
        });
        planSelect.dispatchEvent(new Event('change'));
    });
</script>

web.php

Route::get('/findIDTime', [AppHttpControllersHomeController::class, 'findIDTime'])->name('findIDTime');

HomeController.php

public function findIDTime(Request $request)
{
    $data = Time::query()->where('plan_id', $request->id)->get();
    return $data;
}

2

Answers


  1. To understand what you mean, if you have already set the plan price in the database table, and what you want is the price to be displayed after choosing one of the plans through selection, right?

    You can try this method, it may help in solving the problem

    In the control, add this code

    public function findIDTime(Request $request)
    {
         $planId = $request->input('id');
         $plan = Plan::find($planId);
    
         return response()->json([
             'price' => $plan->price,
         ]);
    }
    

    JS code

    document.addEventListener('DOMContentLoaded', function() {
        var planSelect = document.getElementById('plan_id');
        var timeSelect = document.getElementById('time_id');
        var priceTotal = document.getElementById('totalPrice');
        
        planSelect.addEventListener('change', function() {
            var planId = this.value;
            var xhr = new XMLHttpRequest();
            
            xhr.open('GET', '/findIDTime?id=' + planId, true);
            
            xhr.onload = function() {
                if (xhr.status === 200) {
                    var data = JSON.parse(xhr.responseText);
                    timeSelect.innerHTML = '';
                    
                    for (var i = 0; i < data.length; i++) {
                        var option = document.createElement('option');
                        option.value = data[i].id;
                        
                        if (data[i].direction === 1) {
                            option.textContent = data[i].start_time + ' صبح';
                        } else {
                            option.textContent = data[i].start_time + ' عصر';
                        }
                        
                        timeSelect.appendChild(option);
                    }
                    
                    priceTotal.innerText = data[0].price;
                } else {
                    console.log('Error: ' + xhr.status);
                }
            };
            
            xhr.onerror = function() {
                console.log('Request failed');
            };
            
            xhr.send();
        });
    
        planSelect.dispatchEvent(new Event('change'));
    });
    

    Based on a comment in my first answer "I get this error Uncaught TypeError: data[0] is undefined" 👇

    The error you encountered "TypeError: Data[0] is undefined" indicates that an attempt to access data[0] in your code occurs when the data is undefined or empty.

    In this case, it looks like you are assigning the value to PriceTotal.innerText using data[0].price, but it may happen that the data is not an array or the first element in the array is not defined.

    To avoid this error, you can add an additional check to ensure that the data is not empty and contains elements before attempting to access the data[0]. You can check this by adding a condition before using data[0] like so:

    document.addEventListener('DOMContentLoaded', function() {
        var planSelect = document.getElementById('plan_id');
        var timeSelect = document.getElementById('time_id');
        var priceTotal = document.getElementById('totalPrice');
        
        planSelect.addEventListener('change', function() {
            var planId = this.value;
            var xhr = new XMLHttpRequest();
            
            xhr.open('GET', '/findIDTime?id=' + planId, true);
            
            xhr.onload = function() {
                if (xhr.status === 200) {
                    var data = JSON.parse(xhr.responseText);
                    timeSelect.innerHTML = '';
                    
                    if (data.length > 0) {
                        for (var i = 0; i < data.length; i++) {
                            var option = document.createElement('option');
                            option.value = data[i].id;
                            
                            if (data[i].direction === 1) {
                                option.textContent = data[i].start_time + ' صبح';
                            } else {
                                option.textContent = data[i].start_time + ' عصر';
                            }
                            
                            timeSelect.appendChild(option);
                        }
                        
                        priceTotal.innerText = data[0].price;
                    } else {
                        console.log('No data available');
                    }
                } else {
                    console.log('Error: ' + xhr.status);
                }
            };
            
            xhr.onerror = function() {
                console.log('Request failed');
            };
            
            xhr.send();
        });
    
        planSelect.dispatchEvent(new Event('change'));
    });
    
    Login or Signup to reply.
  2. Here’s the part of your code that needs modification:

    timeSelect.appendChild(option);
    priceTotal.innerText = data[0].price; // Change this line
    

    This will set the innerText of the priceTotal span to the price of the first item in the data array.

    However, if you have multiple times associated with a plan and you want to display the total price of all those times, you might want to calculate the total price separately.

    Here’s how you can modify your JavaScript code to calculate the total price and display it:

    timeSelect.appendChild(option);
    
    // Calculate the total price
    var totalPrice = data.reduce(function (total, time) {
        return total + parseFloat(time.price);
    }, 0);
    
    priceTotal.innerText = totalPrice.toFixed(2); // Display the total price
    

    This code uses the reduce function to sum up all the prices in the data array. It then sets the innerText of priceTotal to the total price.

    Additionally, you might want to format the price for better readability. I added toFixed(2) to round the total price to two decimal places. Adjust this based on your needs.

    Now, this modification should correctly display the total price in the priceTotal span after a select option is chosen.

    You can replace this code. If it works fine, that’s great. Otherwise,
    let me know, and I will modify the code for you.

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            var planSelect = document.getElementById('plan_id');
            var timeSelect = document.getElementById('time_id');
            var priceTotal = document.getElementById('totalPrice');
            planSelect.addEventListener('change', function() {
                var planId = this.value;
                var xhr = new XMLHttpRequest();
                xhr.open('GET', '{{ route('findIDTime') }}?id=' + planId, true);
                xhr.onload = function() {
                    if (xhr.status === 200) {
                        var data = JSON.parse(xhr.responseText);
                        console.log(data);
                        timeSelect.innerHTML = '';
                        for (var i = 0; i < data.length; i++) {
                            var option = document.createElement('option');
                            option.value = data[i].id;
                            if (data[i].direction === 1) {
                                option.textContent = data[i].start_time + ' صبح';
                            } else {
                                option.textContent = data[i].start_time + ' عصر';
                            }
                            timeSelect.appendChild(option);
                            priceTotal.innerText = data[0].price; // I've update this line with `i` to `0`
                        }
                    } else {
                        console.log('Error: ' + xhr.status);
                    }
                };
                xhr.onerror = function() {
                    console.log('Request failed');
                };
                xhr.send();
            });
            planSelect.dispatchEvent(new Event('change'));
        });
    </script>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search