skip to Main Content

I have, on my edit view of a model, a checkbox list whose elements should be initially checked with the correspondent values chosen at the creation of the instance.
Despite I’ve tried a lot, by consulting a lot of web articles and documentation, I couldn’t achieve that purpose.
I have the edit view coded at the same file than the create view, conditionally rendered, with the first one receiving an instance of the model ‘Alquiler’ (at ‘$alquiler’ variable’) and the ‘$editar’ variable with a boolean value setted on ‘true’ on it. I’m using Alpine to pass some values to the Blade component.

So then, in my main view, I have this code:

‘caracteristicas.blade.php’:

@php
    $condiciones = [];
    if($editar) {
        foreach($alquiler->servicios as $servicioOfrecido) {
            foreach($servicios as $servicio) {
                if($servicioOfrecido['id'] == $servicio['id']) {
                    debug_to_console($servicio);  //This is an aux function I've defined to log to the browser some PHP data when needed
                    array_push($condiciones, $servicioOfrecido['id']);
                }
            }
        }
    } 
    else {
        $condiciones[] = false;
    }
@endphp
...
@if($editar)
<form action="{{ route('partes.caracteristicas',$alquiler)}}" method="POST" id="caracteristicas">
@else
<form action="{{ route('partes.caracteristicas')}}" method="POST" id="caracteristicas">
@endif
@csrf
...

    <div x-data='{servicios:@json($servicios),condiciones:@json($condiciones)}' class="w-full">
      <ul class="whitespace-normal">
        <template x-for="(servicio,indice) in servicios" :key="indice">
          <x-check-boton x-bind::id='servicio.identificador' x-bind::texto='servicio.servicio' x-bind::valor='servicio.id' x-bind::condiciones='condiciones'></x-check-boton>
        </template>
      </ul>
    </div>

...

</form>

...

<script>
    console.log(@json($servicios));
    console.log(@json($condiciones));
</script>
...

My code at the blade component is this one:

‘check-boton.blade.php’:

<li class="inline-block" {{$attributes}} x-data="{
          id:'',
          texto:'',
          valor:'',
          condicion:false,
          condiciones:[],
          
          init: function() {
              this.$nextTick( () => {
                 this.id = this.$el.attributes[':id'].value;
                 this.texto = this.$el.attributes[':texto'].value;
                 this.valor = this.$el.attributes[':valor'].value;
                 this.condiciones = this.$el.attributes[':condiciones'].value;e
                 this.condicion = this.condiciones.includes(this.valor);
              });
          }
        
        }">

<div class="flex" x-init='console.log(condiciones)'>
      <input type="checkbox" :id="id" name="servicios[]" :value="valor" class="peer hidden" x-model="condiciones" />
      <label :for="id" class="select-none cursor-pointer rounded-full border-[1px] border-gray-400
                 py-2 px-6 font-light text-gray-800 transition-colors duration-200 ease-in-out
                 peer-checked:bg-emerald-800 bg-transparent peer-checked:text-gray-50 peer-checked:border-none m-2"
                 x-text="texto"></label>
   </div>
</li>

So then, I’m having this result on the browser, showing here also the ‘console.log’s results defined in the main view for debugging purposes, and also the logging coded at the @php/@endphp section:

Browser view

The result at the <div class="flex" x-init='console.log(condiciones)'> is:

Component log

Meaning that the array is not properly received at the component.

I’ve tried some other stuff, like doing in the component:

<li class="inline-block" {{$attributes}} x-data="{
  id: '',
  texto: '',
  valor: '',
  condiciones: [],
  condicion: false,
  init: function() {
    this.$nextTick(() => {
      this.id = this.$el.attributes[':id'].value;
      this.texto = this.$el.attributes[':texto'].value;
      this.valor = this.$el.attributes[':valor'].value;
      this.condiciones = JSON.parse(this.$el.attributes[':condiciones'].value);
      this.condicion = this.condiciones.includes(parseInt(this.valor));
    });
  }
}">
 ....
</li>

But I’m getting at the console:

Uncaught SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at eval (eval at <anonymous> (app-7a4f3435.js:48:671), <anonymous>:14:31)
    at app-7a4f3435.js:48:3704
    at Ri (app-7a4f3435.js:48:3761)
    at app-7a4f3435.js:48:3666
eval @ VM1105:14
(anonymous) @ app-7a4f3435.js:48
Ri @ app-7a4f3435.js:48
(anonymous) @ app-7a4f3435.js:48
setTimeout (async)
(anonymous) @ app-7a4f3435.js:48

I’ve also tried using ‘condicion’ instead of ‘condiciones’ in the ‘x-model’ like this:
<input type="checkbox" :id="id" name="servicios[]" :value="valor" class="peer hidden" x-model="condicion" />

Any idea of what I’m doing wrong? Any more info needed?

If necessary, I can share the section of the controller with the relevant methods for this issue, an also the content of some ‘Alquiler’ instance, obtained by tinker, as an example.

Thanks a lot!

Leandro

2

Answers


  1. Chosen as BEST ANSWER

    @Pippo Despite your suggested solution should work, I finally could solve this issue like this:

    'caracteristecas.blade.php':

    <div x-data='{servicios:@json($servicios),condiciones:@json($condiciones)}' class="w-full">
      <ul class="whitespace-normal">
        <template x-for="(servicio,indice) in servicios" :key="indice">
          <x-check-boton></x-check-boton>
        </template>
      </ul>
    </div>
    

    'check-boton.blade.php':

    <li class="inline-block" x-data="{
              id:servicio.identificador,
              texto:servicio.servicio,
              valor:servicio.id}">
    
       <div class="flex">
          <input type="checkbox" :id="id" name="servicios[]" :value="valor" class="peer hidden" x-model="condiciones" />
          <label :for="id" class="select-none cursor-pointer rounded-full border-[1px] border-gray-400
                     py-2 px-6 font-light text-gray-800 transition-colors duration-200 ease-in-out
                     peer-checked:bg-emerald-800 bg-transparent peer-checked:text-gray-50 peer-checked:border-none m-2"
                     x-text="texto"></label>
       </div>
    </li>
    

    Despite the section

     init: function() {
        this.$nextTick(() => {
        ...
    

    Worked for other values, it doesn't update at the needed moment the value of the array 'condiciones[]', resulting in an empty array when I refer to it on 'x-model'

    Thanks a lot!

    Leandro


  2. One solution can be passing the list of values to the component using the PHP and imploding it:

    <x-check-boton x-bind::id='servicio.identificador'
                   x-bind::texto='servicio.servicio'
                   x-bind::valor='servicio.id'
                   condiciones="{{ implode(';', $condiciones )}}"
    >
    

    then in the init() function the values can be extracted by splitting the string:

    init: function() {
    
      this.$nextTick( () => {
    
         this.id = this.$el.attributes[':id'].value;
         this.texto = this.$el.attributes[':texto'].value;
         this.valor = this.$el.attributes[':valor'].value;
    
         this.condiciones = this.$el.attributes['condiciones'].value.split(';');
    
         this.condicion = this.condiciones.includes(this.valor);
      });
    }
    

    but, since the child component inherits the parent’s properties, I think a better solution would be to completely remove the condiciones property from the check-boton component, so each child will refer to the parent’s condiciones list:

    <x-check-boton x-bind::id='servicio.identificador'
                   x-bind::texto='servicio.servicio'
                   x-bind::valor='servicio.id'
    >
    

    in the child component:

    <li class="inline-block" {{$attributes}} 
        x-data="{
           id:'',
           texto:'',
           valor:'',
           condicion:false,
    
           init: function() {
     
               this.$nextTick( () => {
    
                   this.id = this.$el.attributes[':id'].value;
                   this.texto = this.$el.attributes[':texto'].value;
                   this.valor = this.$el.attributes[':valor'].value;
                   this.condicion = this.condiciones.includes(this.valor);
               });
           }
            
    }">
    

    In any case the x-model must be set on condicion

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search