DEV Community

Cover image for How to create dynamic input fields with Laravel Livewire.

How to create dynamic input fields with Laravel Livewire.

Jonathon Ringeisen on November 27, 2021

Hey there đź‘‹, I recently ran into a situation where I needed to build a dynamic input field and thought I would share how I did it. This how-to is ...
Collapse
 
bleriotnoguia profile image
BlĂ©riot Noguia • Edited

Thanks ! Brother. I noticed that when I click "Remove Input" and then try to add a new input again, the "Add New Option" button no longer works. I solved this issue by changing the div tag from "Add new option" with a button tag.

<button wire:click="addInput" class="flex items-center justify-center text-blue-600 text-sm py-4 w-full cursor-pointer">
    <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11a1 1 0 10-2 0v2H7a1 1 0 100 2h2v2a1 1 0 102 0v-2h2a1 1 0 100-2h-2V7z" clip-rule="evenodd"></path></svg>
    <p class="ml-2">Add New Option</p>
</button>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
bhushancodesdot profile image
Bhushan • Edited

How Can fully Dynamic Validation in livewire Laravel

Controller

foreach ($request->all() as $key => $value) {
            if (strpos($key, 'textarea_') === 0 || strpos($key, 'textbox_') === 0 ) {
                $questionId = substr($key, strpos($key, '_') + 1);
                if($key == "textbox_78" || $key == "textbox_77"){
                     $rules['textbox_78'] = 'required|integer|min:1800|max:2024';
                     $rules['textbox_77'] = 'required|integer|between:1,12';
                     $messages['textbox_78' . '.required'] = 'This field is required';
                     $messages['textbox_78' . '.integer'] = 'Please enter an integer value';
                     $messages['textbox_78' . '.min'] = 'The value must be at least 1800';
                     $messages['textbox_78' . '.max'] = 'The value cannot exceed current Year';

                     $messages['textbox_77' . '.required'] = 'This field is required';
                     $messages['textbox_77' . '.integer'] = 'Please enter an integer value';
                     $messages['textbox_77' . '.between'] = 'Value between 1 and 12';
                     $messages['textbox_77' . '.size'] = 'size will 2 digit like 01';
                }else{
                     $rules[$key] = 'required';
                     $messages[$key . '.required'] = 'This field is required';
                }

            }
        }
Enter fullscreen mode Exit fullscreen mode

Blade file

 @if($question->type == 'textbox')
    <div class="grid grid-cols-12 gap-3 {{ $loop->even ? 'bg-white' : 'bg-darkbg' }}">
        <div class="col-span-6">
            <label class="block py-3 pl-4">{{ $question->name }}</label>
        </div>
        <div class="text-center  p-3"> 
            <input type="text" id="{{ $question->id }}" name="textbox_{{ $question->id }}" class="rounded-sm border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-black placeholder:text-black text-sm sm:leading-6">
        </div>  
        @if($errors->has('textbox_' . $question->id))
            <div class="error" style="color:red; margin-top: 55px; margin-left: -110px;">{{ $errors->first('textbox_' . $question->id) }}</div>
        @endif             
    </div>
@endif 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
willvincent profile image
Will Vincent

Good stuff Jonathon. Thanks for sharing

Collapse
 
jringeisen profile image
Jonathon Ringeisen

Thanks! Anytime.

Collapse
 
ilearnbydoing profile image
Durgesh Gupta

how to perform inline calculation i.e. in case of invoice qty*price to get inline total?

Collapse
 
jringeisen profile image
Jonathon Ringeisen

I'm actually building an invoicing feature that does just this. I have a collection called inputs and this is where all the input data lives. Then I do the following:

public function updatedInputs()
{
    $this->formatMappedInputs();
    $this->calculateTotals();
}

public function formatMappedInputs()
{
    $this->mapped_inputs = $this->inputs->map(function ($row) {
        $total = 0;
        $subtotal = 0;

        if ($row['price'] > 0) {
            $total += $row['price'];
            $subtotal += $total;
        }

        if (isset($row['quantity']) && $row['quantity'] > 0) {
            $total = $total * $row['quantity'];
            $subtotal = $total;
        }

        if (isset($row['discount']) && $row['discount'] > 0) {
            $total = $total - ($total * ($row['discount'] / 100));
        }

        return [
            'item' => $row['item'],
            'price' => $row['price'],
            'quantity' => $row['quantity'],
            'discount' => $row['discount'],
            'subtotal' => $subtotal,
            'total' => $total,
        ];
    });
}

public function calculateTotals()
{
    $subtotal = $this->mapped_inputs?->sum('subtotal');
    $discount = $this->mapped_inputs?->sum('subtotal') - $this->mapped_inputs?->sum('total');
    $total = $this->mapped_inputs?->sum('total');

    $this->totals = [
        'subtotal' => $this->formatCurrencyToUsd($subtotal),
        'discount' => $this->formatCurrencyToUsd($discount),
        'total' => $this->formatCurrencyToUsd($total),
    ];
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ilearnbydoing profile image
Durgesh Gupta • Edited

I used wire:change on blade

<input type="number" class="form-control form-control-sm text-center" 
id="input_{{$key}}_price" wire:model.defer="inputs.{{$key}}.price" 
wire:change="inlineTotal" >
Enter fullscreen mode Exit fullscreen mode

to call inlineTotal

  public function inlineTotal()
    {
        $this->inputs = $this->inputs->map(function ($item) {
            return [
                'title' => $item['title'],
                'description'  => $item['description'],
                'hsn_sac'  => $item['hsn_sac'],
                'bale_no'  => $item['bale_no'],
                'qty_per_box'  => $item['qty_per_box'],
                'no_of_boxes'  => $item['no_of_boxes'],
                'qty' => $item['qty'],
                'price' => $item['price'],
                'total_price' => $item['price'] * $item['qty'],
            ];
        });
    }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ilearnbydoing profile image
Durgesh Gupta

thanks

Collapse
 
mafalda2007 profile image
Mafalda

Muy bueno! Good!

Collapse
 
franco04508550 profile image
Franco

Very good but how could I dynamically enter that data in a save method?

Collapse
 
jaguar988 profile image
jaguar988 • Edited

Thanks Bro! but when i add js datepicker with inputs does not work for me