Search code examples
jquerylaravel-livewirealpine.js

How can I make a checkbox be always checked by getting its value?


For this task I'm working with laravel-livewire, alpine.js and bootstrap.

I have a modal in my screen which contains a table where the user can select up to 9 columns to show. There is one column that needs to appear by default in all cases (so it needs to be checked by default) and as I said, the user will select another 9.

Here is the construction of the table:

<tbody>
   <template x-for="column in data" >
      <tr x-show="column.title != ''">
         <td class="text-left ml-4"> 
            <span x-html="column.title"></span> 
         </td>
         <td class="text-left">
            <input 
               x-model="selectedColumns" 
               id="selectColumns" 
               class="selectColumns" 
               type="checkbox" 
               :value=column.field
               >
         </td>
      </tr>
   </template>
</tbody>

In the :value attribute, I'm receiving names of my database fields. The one that I need to appear by default for example is named sap_id

The code I'm using to limit columns selection:

$(document).ready(function () {
    $("input[id='selectColumns']").change(function () {
        var maxAllowed = 8;
        var selected = $("input[id='selectColumns']:checked").length;
        
        if (selected > maxAllowed) {
            $("input[id='selectColumns']").not(":checked").attr("disabled",true);
        } else {
            $("input[id='selectColumns']").not(":checked").removeAttr('disabled');
        }       
    });
});

And finally, the function that displays the selected columns in the screen:

function displaySelected(selectedColumns) {
    let newColumns = columns.filter((column) => {
       return selectedColumns.includes(column.field);
    });

    datatable.destroy();
    $('#selectColumnsModal').modal('hide');
    Clients.init(newColumns);
}

So, summing up: If the :value attribute equals to sap_id the checkbox needs to be checked by default and may not be unchecked. I'm having trouble on making this work. Actually I don't even know if this is the best way for doing this task... So if you guys could help me with that I would be very pleased. Thanks in advance!


Solution

  • In this example I created a list for default columns: defaultSelected, that we can add to the selected list in the init() function of our columnSelector component. Furthermore in the isDisabled(field) function we also check whether the respective column is present in defaultSelected or not.

    Note: uncomment the document.addEventListener line, it's disabled because of SO code snippet window only.

    <script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
    <script>
    //document.addEventListener('alpine:init', () => {
      Alpine.data('columnSelector', () => ({
        defaultSelected: ['sap_id'],
        maxSelected: 3,
        data: [
          {title: 'SAP ID', field: 'sap_id'},
          {title: 'Col #1', field: 'field1'},
          {title: 'Col #2', field: 'field2'},
          {title: 'Col #3', field: 'field3'},
          {title: 'Col #4', field: 'field4'},
          {title: 'Col #5', field: 'field5'},
        ],
        selectedColumns: [],
    
        init() {
          this.selectedColumns.push(...this.defaultSelected)
        },
    
        isDisabled(field) {
          return this.defaultSelected.includes(field) ||
                 (this.selectedColumns.length === this.maxSelected &&
                  !this.selectedColumns.includes(field))
        },
      }))
    //})
    </script>
    
    <div x-data="columnSelector">
      <table>
        <tbody>
          <template x-for="column in data" >
              <tr x-show="column.title != ''">
                <td class="text-left ml-4">
                    <span x-html="column.title"></span>
                </td>
                <td class="text-left">
                    <input
                      x-model="selectedColumns"
                      class="selectColumns"
                      type="checkbox"
                      :value=column.field
                      :disabled="isDisabled(column.field)"
                      >
                </td>
              </tr>
          </template>
        </tbody>
      </table>
      Selected columns: <span x-text="`${selectedColumns.length}/${maxSelected}`"></span>
    </div>