4

I am trying to fetch country codes from my database and trying to get the default value via IP address. It works just as I want for a second but then I don't know what happens but it refreshes itself and scrolls to the first option instead of the selected option.

Livewire Controller Component

use App\Models\CountryCodes;
use Livewire\Component;
use Location;

class TestCountry extends Component
{
    public $iso;
    public $country_codes;
    public $country_code;

    public function mount()
    {
        $iso=Location::get('ip');
        $this->iso=$iso->countryCode;
    }

    public function render()
    {
        return view('livewire.test-country',[
            $this->country_codes = CountryCodes::select('nicename','iso','phonecode')->get()->toArray()
        ]);
    }
}

Livewire Blade Component

<select wire:model.lazy="country_code" name="country_code" id="country_code" class="form-control" required>
    @foreach($country_codes as $country_code)
        <option value="{!! $country_code['iso'] !!}"
                wire:key="{{$country_code['iso']}}"
                {{ $country_code['iso'] == $iso ? 'selected' : ''}}>
            {!! $country_code['iso'] !!} +{!! $country_code['phonecode'] !!}
        </option>
    @endforeach
</select>

This code does select my default option but it changes and moves to the first option automatically. Am I doing something wrong here?

1 Answer 1

8

I believe what is happening is, $iso is set correctly, but the select is bound to the $country_code property, not $iso, so briefly, the check you have works, but because $country_code doesn't have a value, the selected option is lost when the state is updated by Livewire.

TLDR: Livewire is checking whatever is in the wire:model attribute, so the class property must be set for it to work.

I would try something like this:

public function mount()
{
    $iso = Location::get('ip');
    $this->iso = $iso->countryCode;

    // set $country_code to $iso
    $this->country_code = $this->iso;
}

I believe Livewire will intelligently select the state, so I think the selected check can be removed:

<select wire:model.lazy="country_code" name="country_code" id="country_code" class="form-control" required>
    @foreach($country_codes as $country_code)
        <option
            value="{!! $country_code['iso'] !!}"
            wire:key="{{$country_code['iso']}}"
        >
            {!! $country_code['iso'] !!} +{!! $country_code['phonecode'] !!}
        </option>
    @endforeach
</select>

Also, any reason for using {!! !!} tags in the view rather than just {{ }}?

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

5 Comments

Wow, this worked just the way I wanted it to. Had no clue about this solution. Thanks a lot. Honestly, I used {!! !!} just without any proper reason will be changing it to {{ }} right away. Also, can you tell me if there is any way like by using wire:model it sends request again and again to livewire controller due to which my wire:loading div loads, again and again, let it be even on few keypresses. Is there any way to avoid it and send data to validate via livewire only when submit button is clicked?
No probs, glad it works. I'd change wire:model.lazy to wire.model.defer if that's what you want, that's what I tend to use most of the time too, the docs on it are here: laravel-livewire.com/docs/2.x/properties#deferred-updating
thanks a lot for all the help. It was really helpful was kinda stuck on this since long time.
No problem, glad it helped!
Also can you please upvote the question if you find it was well described.

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.