Updating A Sibling Property

What seems to be the problem:

I am trying to check the amount of selectedCourses and when the count is 0 then update a different property to 0.

Steps to Reproduce:

Are you using the latest version of Livewire: Yes

Do you have any screenshots or code examples:

<?php

namespace App\Http\Livewire;

use App\Models\Course;
use App\Models\Semester;
use Livewire\Component;

class CreateSemesterCourses extends Component
{
protected $listeners = [‘courseRemoved’ => ‘countRemainingCourses’];

/**
 *  @var App\Models\Semester
 */
public Semester $semester;

/**
 * List of all courses.
 *
 * @var array
 */
public $courses;

/**
 * Semester that will duplicated.
 *
 * @var int
 */
public $semesterIdToDuplicate;

/**
 * List of courses of semester to duplicate.
 *
 * @var array
 */
public $selectedCourses;

/**
 * Apply properties to the instance.
 *
 * @param  App\Models\Semester $semester
 * @return void
 */
public function mount(Semester $semester)
{
    $this->semester = $semester;
    $this->courses = Course::allForDropdown()->toArray();
}

/**
 * Display a list of resources.
 *
 * @return \Illuminate\View\View
 */
public function render()
{
    return view('livewire.semesters.create-semester-courses', [
        'semesters' => Semester::orderBy('start_date')->pluck('name', 'id')->prepend('Please choose a semester', '0'),
        'semester' => $this->semester,
        'courses' => $this->courses,
    ]);
}

/**
 * Updates selected courses of semester to duplicate.
 *
 * @param  int $value
 * @return array
 */
public function updatedSemesterIdToDuplicate($value)
{
    if ($value == 0) {
        $this->dispatchBrowserEvent('livewire:load');

        return $this->selectedCourses = [];
    }

    $duplicateSemester = Semester::find($value);

    $courses = $duplicateSemester->courseSections->map(function ($section) {
        return $section->course;
    });

    $uniqueCourses = $courses->unique(function ($course) {
        return $course->name;
    });

    $uniqueCourses->map(function ($course) {
        return [
            'label' => $course->name,
            'value' => $course->id,
        ];
    })->toArray();

    $this->selectedCourses = $uniqueCourses->pluck('id')->toArray();

    $this->dispatchBrowserEvent('livewire:load');
}

public function countRemainingCourses()
{
    if (count($this->selectedCourses) == 0) {
        $this->semesterIdToDuplicate = 0;

        $this->dispatchBrowserEvent('livewire:load');
    }

    $this->dispatchBrowserEvent('livewire:load');
}

}

@push(‘scripts’)

// Class definition
var KTDualListbox = function() {
// Private functions
var coursesListBox = function () {
// Dual Listbox
var _this = document.getElementById(‘courses_listbox’);

        // init dual listbox
        var dualListBox = new DualListbox(_this, {
            addEvent: function (value) {

            },
            removeEvent: function (value) {
                Livewire.emit('courseRemoved')
            },
            availableTitle: 'Available courses',
            selectedTitle: 'Selected courses',
            addButtonText: 'Add',
            removeButtonText: 'Remove',
            addAllButtonText: 'Add All',
            removeAllButtonText: 'Remove All',
        });
    };

    return {
        // public functions
        init: function() {
            coursesListBox();
        },
    };
}();

window.addEventListener('livewire:load', function() {
    KTDualListbox.init();
});
</script>

Hi,

Could you add an updated hook to the component for the selectedCourses property?

public function updatedSelectedCourses($value)
{
    if (count($value) === 0) {
        $this->whateverProperty = 0;
    }
}

I haven’t checked to see if this works but is this along the lines if what you are after?

Hope this helps.

Unfortunately that doesn’t help. I"m updating the problem here.

I’m trying to figure out two things.

  1. When I have semesterIdToDuplicate set to a value of 0 and I add more than one course to to the selectedCourses array then remove one of them, they all get removed from the selectedCourses array.

Does anyone see why this happens?

  1. If I have the semesterIdToDuplicate set to anything other than 0 and selectedCourses has more than 0 items in its array, once a selectedCourse is removed then I have semesterIdToDuplicate set to 0 which wuallorks but it doesn’t actually remove that one item.

Not sure with this isn’t working.

I have included the Livewire component as well as the blade attached to the component.

<?php

namespace App\Http\Livewire;

use App\Models\Course;
use App\Models\Semester;
use Livewire\Component;

class CreateSemesterCourses extends Component
{
    protected $listeners = ['courseRemoved' => 'countRemainingCourses'];

    /**
     *  @var App\Models\Semester
     */
    public Semester $semester;

    /**
     * List of all courses.
     *
     * @var array
     */
    public $courses;

    /**
     * Semester that will duplicated.
     *
     * @var int
     */
    public $semesterIdToDuplicate;

    /**
     * List of courses of semester to duplicate.
     *
     * @var array
     */
    public $selectedCourses;

    /**
     * Apply properties to the instance.
     *
     * @param  App\Models\Semester $semester
     * @return void
     */
    public function mount(Semester $semester)
    {
        $this->semester = $semester;
        $this->courses = Course::allForDropdown()->toArray();
    }

    /**
     * Display a list of resources.
     *
     * @return \Illuminate\View\View
     */
    public function render()
    {
        return view('livewire.semesters.create-semester-courses', [
            'semesters' => Semester::orderBy('start_date')->pluck('name', 'id')->prepend('Please choose a semester', '0'),
            'semester' => $this->semester,
            'courses' => $this->courses,
        ]);
    }

    /**
     * Updates selected courses of semester to duplicate.
     *
     * @param  int $value
     * @return array
     */
    public function updatedSemesterIdToDuplicate($value)
    {
        if ($value == 0) {
            dd('testing');
            if (count($this->selectedCourses) == 0) {
                return $this->selectedCourses = [];
            }

            $this->dispatchBrowserEvent('livewire:load');
        } else {
            $duplicateSemester = Semester::find($value);

            $courses = $duplicateSemester->courseSections->map(function ($section) {
                return $section->course;
            });

            $uniqueCourses = $courses->unique(function ($course) {
                return $course->name;
            });

            $uniqueCourses->map(function ($course) {
                return [
                'label' => $course->name,
                'value' => $course->id,
            ];
            })->toArray();

            $this->selectedCourses = $uniqueCourses->pluck('id')->toArray();

            $this->dispatchBrowserEvent('livewire:load');
        }
    }

    public function countRemainingCourses()
    {
        if ($this->semesterIdToDuplicate != 0 && count($this->selectedCourses) != 0) {
            $this->semesterIdToDuplicate = 0;
        }
    }
}

<div>
    <x-input.group label="Make Duplicate Of" for="semesterIdToDuplicate" :error="$errors->first('duplicate')">
        <x-input.select
            id="semesterIdToDuplicate"
            wire:model="semesterIdToDuplicate"
            :options="$semesters"
            selectedOption="{{ old('semesterIdToDuplicate', $semester->exists ? $semester->default : '')  }}"
        />
    </x-input.group>

    <x-input.group label="Courses" for="courses_listbox" :error="$errors->first('courses')">
        <x-input.dual-listbox
            id="courses_listbox"
            name="courses[]"
            class="dual-listbox"
            :options="$courses"
            :selectedOptions="$selectedCourses"
            multiple
        />
    </x-input.group>
</div>

@push('scripts')
    <script>
    // Class definition
    var KTDualListbox = function() {
        // Private functions
        var coursesListBox = function () {
            // Dual Listbox
            var _this = document.getElementById('courses_listbox');

            // init dual listbox
            var dualListBox = new DualListbox(_this, {
                addEvent: function (value) {

                },
                removeEvent: function (value) {
                    Livewire.emit('courseRemoved')
                },
                availableTitle: 'Available courses',
                selectedTitle: 'Selected courses',
                addButtonText: 'Add',
                removeButtonText: 'Remove',
                addAllButtonText: 'Add All',
                removeAllButtonText: 'Remove All',
            });
        };

        return {
            // public functions
            init: function() {
                coursesListBox();
            },
        };
    }();

    window.addEventListener('livewire:load', function() {
        KTDualListbox.init();
    });
    </script>
@endpush

Hi, working with checkbox group is a little different in livewire and also is somehow confusing

This is how I work with checkbox groups, this is an example adapt to yours needs

First the property that will hold my values an array

public $semesterIdToDuplicate=[];
public $semesters;
public mount()
{
$this->semesters=App\Model\Semester::all()
}

blade

@foreach($semesters as $semester)
            <label for="{{$semester->id}}" value="{{$semester->name}}"></label>
            <input type="checkbox" id="{{$semester->id}}" value="{{$semester->id}}"  wire:model="semesterIdToDuplicate.{{$loop->index}}"/>
@endforeach

Look instead of assign it the hole array variable now I’m using the array index, then when you check an specific value, that value will be assign it to the index of that array property.

Aditional note for some reason livewire when you uncheck an item from the list , it let that item with the value of false, so I made this little workaround to solve that problem.
with the function below you will completely remove unchecked items, that function is execute everytime that specific property is updated

public function updatedSemesterIdToDuplicate($value)
{

    $this->semesterIdToDuplicate=Arr::where($this->semesterIdToDuplicate, function ($value) {
        return $value!==false;
    });
}

that will solve your problem, any question let me know