vmutius's avatar

Populate Column Dropdown in blade

Hello I want to populate the columns of a table in a dropdown menu so that the user can select one. My controller

<?php

namespace App\Http\Livewire\User;

use App\Models\Application;
use App\Models\Enclosure;
use App\View\Components\Layout\UserDashboard;
use Illuminate\Support\Facades\Schema;
use Livewire\Component;
use Livewire\WithFileUploads;

class Datei extends Component
{
    use WithFileUploads;
    public $showModal = false;

    public $enclosures;

    public $applications;

    public $name;

    public $UserName;

   public $application_id;

   public $column;

   public $file;

   public $columns;

    protected function rules(): array
    {
        return [
            'application_id' => 'required',
            'column' => 'required',
            'file' => 'required',
        ];
    }

    public function mount()
    {
        $this->applications = Application::with('enclosure')->LoggedInUser()->get();
        foreach ($this->applications as $application)
        {
            $this->enclosures=Enclosure::where('application_id', $application->id)->get();
        }

        $lastname = auth()->user()->lastname;
        $firstname = auth()->user()->firstname;
        $this->UserName = $lastname.'_'.$firstname;
    }

    public function render()
    {
        return view('livewire.user.datei')
            ->layout(UserDashboard::class);
    }

    public function addEnclosure()
    {
        $this->showModal = true;

    }

    public function saveEnclosure()
    {
        $this->file = $this->upload($this->newEnclosure->column, 'activity');

    }

    public function updatedApplicationId($application_id) {
        $enclosure = Enclosure::where('application_id', $application_id)->first();
        $columns = Schema::getColumnListing($enclosure->getTable());

        dd($columns);
    }

    public function close()
    {
        $this->showModal = false;
    }

    public function upload($type, $text)
    {
        if (! is_null($type)) {
            $appl_id = session()->get('appl_id');
            $fileName = 'Appl'.$appl_id.'_'.$text.'.'.$type->getClientOriginalExtension();
            $file = $type->storeAs($this->UserName, $fileName, 'uploads');

            return $file;
        }
    }
}

And my blade view

<section class="home-section">
    <div class="text">Dateien</div>

    <div class="home-content">
        <div class="shadow p-3 mb-5 bg-body rounded">
            <div class="row">
                <div class="col-md-12">
                    <button class="btn btn-colour-1  btn-next pull-right" wire:click="addEnclosure()">Neue Datei hochladen</button>
                </div>
            </div>
            <hr class="border border-dark opacity-50">
            <x-notification/>
            <table class="table table-striped">
                <thead>
                    <tr>
                        <th>Inhalt</th>
                        <th>Datei</th>
                        <th>Antrag</th>
                        <th>Erstellt</th>
                        <th>Zuletzt Geändert</th>
                    </tr>
                </thead>
                <tbody>
                @forelse ($enclosures as $enclosure)
                    @foreach($enclosure->getAttributes() as $column => $value)
                        @if(in_array($column, ['id', 'created_at', 'updated_at', 'application_id', 'remark']))
                            @continue
                        @endif

                        @if($value)
                            <tr>
                                <td>{{ __('enclosure.'.$column) }}</td>
                                <td><a href="{{ asset('uploads/'.$enclosure->$column) }}"
                                       target="_blank">{{ $enclosure->$column }}</a></td>
                                <td>{{ $enclosure->application->name }}</td>
                                <td>{{ $enclosure->application->created_at ? $enclosure->application->created_at->format('d.m.Y H:i') : null }}</td>
                                <td>{{ $enclosure->application->updated_at ? $enclosure->application->updated_at->format('d.m.Y H:i') : null }}</td>

                            </tr>
                        @endif
                        @endforeach
                    @empty
                        <tr>
                            <td colspan="5">Keine Dateien gefunden</td>
                        </tr>
                    @endforelse
                </tbody>
            </table>
        </div>

        <div class="modal" @if ($showModal) style="display:block" @endif>
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <form wire:submit.prevent="saveEnclosure">
                        <div class="modal-header">
                            <h5 class="modal-title">Neue Datei hochladen</h5>
                            <button wire:click="close" type="button" class="close" data-dismiss="modal"
                                aria-label="Close">
                                <span aria-hidden="true">&times;</span>
                            </button>
                        </div>
                        <div class="modal-body">
                            Antrag:
                            <br />
                            <select wire:model.lazy="application_id" class="form-select">
                                <option selected value="">Bitte auswählen...</option>
                                @foreach ($applications as $application)
                                    <option value="{{ $application->id }}">{{ $application->name }}</option>
                                @endforeach
                            </select>
                            @error('application_id')
                                <div style="font-size: 0.75rem; color: red">{{ $message }}</div>
                            @enderror
                            <br />
                            Typ der Datei:
                            <br />
                            <select wire:model.lazy="column" class="form-select">
                                <option selected value="">Bitte auswählen...</option>
                                @foreach($columns as $column => $value)
                                    @if(in_array($column, ['id', 'created_at', 'updated_at', 'application_id', 'remark']))
                                        @continue
                                    @endif
                                    {{ __('enclosure.'.$column) }}
                                @endforeach
                            </select>
                            @error('column')
                                <div style="font-size: 0.75rem; color: red">{{ $message }}</div>
                            @enderror

                            <br />
                            Datei:
                            <br />
                            <input wire:model.defer="activity" class="form-control" type="file">
                            @error('form')
                                <div style="font-size: 0.75rem; color: red">{{ $message }}</div>
                            @enderror
                            <br />
                        </div>
                        <div class="modal-footer">
                            <button type="submit" class="btn btn-primary">Speichern</button>
                            <button wire:click="close" type="button" class="btn btn-secondary"
                                data-dismiss="modal">Close
                            </button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</section>

When I dd the colums after the update of the application id, I get an array with the colums, but when I try to render it I get an error "foreach() argument must be of type array|object, null given".

I have no idea what is wrong here.

0 likes
4 replies
LaryAI's avatar
Level 58

It seems like the issue you're facing is related to the $columns variable not being properly set or updated in your Livewire component. When you use dd($columns); in the updatedApplicationId method, you're able to see the columns because you're directly assigning the result of Schema::getColumnListing to the $columns variable within that method. However, this does not update the component's public $columns property, which is what your Blade view is trying to iterate over.

To fix this, you should update the public $columns property within the updatedApplicationId method so that it's available to the Blade view. Here's how you can modify your Livewire component:

public function updatedApplicationId($application_id) {
    $enclosure = Enclosure::where('application_id', $application_id)->first();
    if ($enclosure) {
        $this->columns = Schema::getColumnListing($enclosure->getTable());
    } else {
        $this->columns = [];
    }
}

And then in your Blade view, you should be able to iterate over $columns without any issues:

<select wire:model.lazy="column" class="form-select">
    <option selected value="">Bitte auswählen...</option>
    @foreach($columns as $column)
        @if(in_array($column, ['id', 'created_at', 'updated_at', 'application_id', 'remark']))
            @continue
        @endif
        <option value="{{ $column }}">{{ __('enclosure.'.$column) }}</option>
    @endforeach
</select>

Make sure that the $columns property is declared as public in your Livewire component so that it's accessible in the Blade view:

public $columns = [];

With these changes, your dropdown should be populated with the columns from the selected application's enclosure table when the application ID is updated.

vmutius's avatar

Ok, but now I get the ids and not the name. $column->name or $column['name'] or $column['value'] does not work

vmutius's avatar

I figured it out now. This works

@foreach($this->columns as $column => $value)
                                    @if(in_array($column, ['id', 'created_at', 'updated_at', 'application_id', 'remark']))
                                        @continue
                                    @endif
                                        <option value="{{ $column }}">{{ __('enclosure.'.$value) }}</option>
                                @endforeach

for the name, but this foreach loop ignores the @continue. So it also displays this values in the dropdown. Any idea why?

vmutius's avatar

Solved, also needed to put $value in the in_array query

Please or to participate in this conversation.