No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    1. Home
    2. fenchai
    F
    • Profile
    • Following 0
    • Followers 0
    • Topics 6
    • Posts 9
    • Best 0
    • Groups 0

    fenchai

    @fenchai

    0
    Reputation
    3
    Profile views
    9
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    fenchai Follow

    Latest posts made by fenchai

    • RE: Trouble with collecting selected items from QTable

      @tof06 I thought this

      computed: {
          ...mapGetters("central", ["searchTerm", "selectedTableData"])
        },
      

      already did the job.

      I guess I will use 2-way-computed thanks for the info

      posted in Help
      F
      fenchai
    • Can't change QTable Column width

      This is what I have that is working ok-ish:
      width: 'Npx' does nothing

      <template v-slot:body-cell-description="props">
              <q-td :props="props" :style="{ width: '50px', whiteSpace: 'normal' }">
                <div class="tableCell">
                  {{ props.value }}
                </div>
              </q-td>
            </template>
      

      What I have tried:
      this method from googling

      cols: [
      {
      name: “status”,
      align: “left”,
      filter: true,
      sortable: true,
      style: ‘width: 40px’,
      type: “string”
      },
      ]
      
      posted in Help
      F
      fenchai
    • Trouble with collecting selected items from QTable

      OK I lied, but not.

      I have a QTable with multi select, it works fine. but the project was getting a bit too big so I decided to separate into modules. But now I would need to somehow pass the selected data into the module(s).

      I decided to use Vuex for this.

      The Problem:

      The Qtable does not have an API for detecting what items are selected or deselected. There are 2 API Events for Selections:

      1. @selection -> function(details) This one is not very useful because it only detects what item got selected or deselected. It triggers before the array of selection is modified. I am not able to get the modified array. (maybe I could with some workaround but is this the way?)

      2. @update:selected -> function(newSelected) This one is the one QTable uses for updating the selected item’s array. The problem with t his one is that it does not triggers when the array is empty.

      My current template is using @selection -> function(details) method to update the selected array in vuex store but there is a delay of 1 change because the method triggers before the array is modified.

      <template>
        <div>
          <q-table
            ref="mainTable"
            class="my-sticky-virtscroll-table"
            style="height: 800px"
            :data="tableData"
            :columns="columns"
            row-key="CODIGO"
            :selected-rows-label="getSelectedString"
            selection="multiple"
            :selected.sync="selected"
            virtual-scroll
            :pagination.sync="pagination"
            :rows-per-page-options="[0]"
            :virtual-scroll-sticky-size-start="48"
            :filter="term"
            flat
            bordered
            @focusin.native="activateNavigation"
            @focusout.native="deactivateNavigation"
            @keydown.native="onKey"
            @selection="onSelect"
          >
            <template v-slot:top-left>
              <q-input
                ref="mainSearchInput"
                debounce="0"
                v-model="term"
                label="Búsqueda"
                filled
                bottom-slots
                clearable=""
                style="width:500px"
                @input="updateSearchTerm(term)"
              >
                <template v-slot:hint
                  >Puede hacer búsquedas online con commandos.</template
                >
              </q-input>
            </template>
      
            <template v-slot:body-cell-qty="props">
              <q-td :props="props">
                <q-badge
                  :class="{
                    'bg-black': props.value <= 0,
                    'bg-red': props.value > 0,
                    'bg-orange': props.value >= 100 && props.value < 500,
                    'bg-green': props.value >= 500,
                    'text-body1': true
                  }"
                  :label="props.value"
                />
              </q-td>
            </template>
      
            <template v-slot:body-cell-code="props">
              <q-td :props="props">
                <div class="tableCell">{{ props.value }}</div>
              </q-td>
            </template>
      
            <template v-slot:body-cell-description="props">
              <q-td :props="props" :style="{ width: '50px', whiteSpace: 'normal' }">
                <div class="tableCell">
                  {{ props.value }}
                </div>
              </q-td>
            </template>
      
            <!-- <template v-slot:body-cell-qty="props">
              <q-td :props="props">
                <div class="tableCell">{{ props.value }}</div>
              </q-td>
            </template> -->
      
            <template v-slot:body-cell-codAlt="props">
              <q-td :props="props" :style="{ width: '50px', whiteSpace: 'normal' }">
                <div class="tableCell">{{ props.value }}</div>
              </q-td>
            </template>
      
            <template v-slot:body-cell-desAlt="props">
              <q-td :props="props" :style="{ width: '50px', whiteSpace: 'normal' }">
                <div class="tableCell">{{ props.value }}</div>
              </q-td>
            </template>
      
            <template v-slot:body-cell-group="props">
              <q-td :props="props">
                <div class="tableCell">{{ props.value }}</div>
              </q-td>
            </template>
      
            <template v-slot:body-cell-price="props">
              <q-td :props="props">
                <div class="tableCell">{{ props.value }}</div>
              </q-td>
            </template>
      
            <template v-slot:body-cell-discount20="props">
              <q-td :props="props">
                <div class="tableCell">{{ props.value }}</div>
              </q-td>
            </template>
          </q-table>
          <!-- <div class="q-mt-md">Selected: {{ JSON.stringify(selected) }}</div> -->
          <chipDetails></chipDetails>
        </div>
      </template>
      
      <script>
      import path from "path";
      import { remote } from "electron";
      import { Platform } from "quasar";
      import { mapGetters, mapActions } from "vuex";
      
      export default {
        computed: {
          ...mapGetters("central", ["searchTerm", "selectedTableData"])
        },
      
        components: {
          chipDetails: require("components/chipDetails.vue").default
        },
      
        data() {
          return {
            term: "",
            tableData: [],
            selected: [],
            selectedTableData: [],
            navigationActive: false,
            pagination: {
              rowsPerPage: 300
            },
            columns: [
              {
                name: "code",
                required: true,
                label: "Código",
                align: "left",
                // field: row => row.name,
                field: "CODIGO",
                format: val => `${val}`,
                sortable: true
              },
              {
                name: "description",
                align: "left",
                label: "Descipción",
                field: "DESCRIPCION",
                sortable: true
              },
              {
                name: "qty",
                label: "Qty",
                field: "INVENT",
                sortable: true,
                align: "right"
              },
              { name: "codAlt", label: "Cod Alt", field: "COD.ALT.", align: "left" },
              {
                name: "desAlt",
                label: "Desc Alt",
                field: "DESC.ALT.",
                align: "left"
              },
              {
                name: "group",
                label: "Grupo",
                field: "GRUPO",
                align: "left"
              },
              { name: "price", label: "Precio", field: "PRECIO", align: "right" },
              {
                name: "discount20",
                label: "20 %",
                field: "PRECIO",
                align: "right",
                sort: (a, b) => parseInt(a, 10) - parseInt(b, 10)
              }
            ]
          };
        },
      
        methods: {
          ...mapActions("central", ["updateSearchTerm", "updateSelectedTableData"]),
      
          getSelectedString() {
            return (
              this.selected.length +
              " selecionado" +
              (this.selected.length > 1 ? "s" : "") +
              " de " +
              this.tableData.length
            );
          },
      
          activateNavigation() {
            this.navigationActive = true;
          },
      
          deactivateNavigation() {
            this.navigationActive = false;
          },
      
          onSelect(evt) {
            console.log(evt);
            this.updateSelectedTableData(this.selected);
            console.log(this.selected);
          },
      
          onKey(evt) {
            if (
              this.navigationActive !== true ||
              [33, 34, 35, 36, 38, 40].indexOf(evt.keyCode) === -1 ||
              this.$refs.mainTable === void 0
            ) {
              return;
            }
      
            evt.preventDefault();
      
            switch (evt.keyCode) {
              case 36: // Home
                page = 1;
                index = 0;
                break;
              case 35: // End
                page = lastPage;
                index = rowsPerPage - 1;
                break;
              case 33: // PageUp
                page = currentPage <= 1 ? lastPage : currentPage - 1;
                if (index < 0) {
                  index = 0;
                }
                break;
              case 34: // PageDown
                page = currentPage >= lastPage ? 1 : currentPage + 1;
                if (index < 0) {
                  index = rowsPerPage - 1;
                }
                break;
              case 38: // ArrowUp
                if (currentIndex <= 0) {
                  page = currentPage <= 1 ? lastPage : currentPage - 1;
                  index = rowsPerPage - 1;
                } else {
                  index = currentIndex - 1;
                }
                break;
              case 40: // ArrowDown
                if (currentIndex >= lastIndex) {
                  page = currentPage >= lastPage ? 1 : currentPage + 1;
                  index = 0;
                } else {
                  index = currentIndex + 1;
                }
                break;
            }
      
            if (page !== this.pagination.page) {
              this.pagination = {
                ...this.pagination,
                page
              };
      
              this.$nextTick(() => {
                const { computedRows } = this.$refs.mainTable;
                this.selected = [
                  computedRows[Math.min(index, computedRows.length - 1)]
                ];
              });
            } else {
              this.selected = [computedRows[index]];
            }
          }
        },
      
        mounted() {
          if (Platform.is.electron) {
            // get file path
            const filePath = path.join(
              remote.app.getPath("home"),
              "/Dropbox/Sync/inventarioHL.json"
            );
      
            // load the File System to execute our common tasks (CRUD)
            var fs = require("fs");
      
            // read file content
            fs.readFile(filePath, "utf-8", (err, getData) => {
              if (err) {
                alert("An error ocurred reading the file :" + err.message);
              }
              // parse text into json
              var jsonData = JSON.parse(getData);
      
              // add entire data to table
              this.tableData = jsonData;
      
              // console.log(jsonData[0]);
      
              // focus on q-input
              this.$refs.mainSearchInput.$el.focus();
            });
          }
      
          // update the q-input with searchTerm
          this.term = this.searchTerm;
        }
      };
      </script>
      
      <style lang="sass">
      .my-sticky-virtscroll-table
        /* height or max-height is important */
        height: 310px
      
        /* specifying max-width so the example can
          highlight the sticky column on any browser window */
        max-width: 1300px
      
        td:first-child
          /* bg color is important for td; just specify one */
          background-color: #fafafa !important
      
        tr th
          position: sticky
          /* higher than z-index for td below */
          z-index: 2
          /* bg color is important; just specify one */
          background: #fafafa
      
        /* this will be the loading indicator */
        thead tr:last-child th
          /* height of all previous header rows */
          top: 48px
          /* highest z-index */
          z-index: 3
        thead tr:first-child th
          top: 0
          z-index: 1
        tr:first-child th:first-child
          /* highest z-index */
          z-index: 3
      
        td:first-child
          z-index: 1
      
        td:first-child, th:first-child
          position: sticky
          left: 0
      </style>
      
      <style>
      .tableCell {
        font-size: 18px;
      }
      </style>
      

      This is the component I am using to access the selected array

      <template>
        <div class="q-pt-sm">
          <q-chip
            color="secondary"
            text-color="white"
            v-for="(sel, index) in selectedTableData"
            :key="index"
            :label="sel['CODIGO']"
            removable
            @remove="removeSelectedChip(index)"
            clickable
            @click="fixed = true"
          />
          <q-dialog v-model="fixed">
            <q-card>
              <q-card-section>
                <div class="text-h6">Terms of Agreement</div>
              </q-card-section>
      
              <q-separator />
      
              <q-card-section style="max-height: 50vh" class="scroll">
                <p v-for="n in 15" :key="n">
                  Lorem ipsum dolor sit amet consectetur adipisicing elit. Rerum
                  repellendus sit voluptate voluptas eveniet porro. Rerum blanditiis
                  perferendis totam, ea at omnis vel numquam exercitationem aut, natus
                  minima, porro labore.
                </p>
              </q-card-section>
      
              <q-separator />
      
              <q-card-actions align="right">
                <q-btn flat label="..." color="primary" v-close-popup />
                <q-btn flat label="OK" color="primary" v-close-popup />
              </q-card-actions>
            </q-card>
          </q-dialog>
        </div>
      </template>
      
      <script>
      import { mapGetters } from "vuex";
      export default {
        data() {
          return {
            fixed: false
          };
        },
        computed: {
          ...mapGetters("central", ["selectedTableData"])
        }
      };
      </script>
      

      Finally this is the vuex store

      const state = {
        searchTerm: "",
        selectedTableData: []
      };
      
      const mutations = {
        updateSearchTerm(state, term) {
          state.searchTerm = term;
        },
        updateSelectedTableData(state, data) {
          state.selectedTableData = data;
        }
      };
      
      const actions = {
        updateSearchTerm({ commit }, term) {
          commit("updateSearchTerm", term);
        },
        updateSelectedTableData({ commit }, data) {
          commit("updateSelectedTableData", data);
        }
      };
      
      const getters = {
        searchTerm: state => {
          return state.searchTerm;
        },
        selectedTableData: state => {
          return state.selectedTableData;
        }
      };
      
      export default {
        namespaced: true,
        state,
        mutations,
        actions,
        getters
      };
      
      posted in Help
      F
      fenchai
    • Press ESC key to minimize Electron app on any route?

      Is this possible?

      I just want to press X button and trigger electron minimize action.

      posted in Help
      F
      fenchai
    • RE: Selecting on a single CheckBox in Table selects all rows.

      Thank you again lol. You solved 2 of my posts already 🙂 @tof06
      unfortunately I don’t know how to change post as solved and site is not allowing me to edit post title either.

      posted in Help
      F
      fenchai
    • RE: Can't style QTable cell conditionally

      thank you very much

      posted in Help
      F
      fenchai
    • QTable Sticky Column only Sticky on CheckBoxes?

      This is how it looks initially
      a93fbdc4-8ec2-4216-96fb-4b94df52fef7-image.png

      This is what happens when I scroll to the right
      7a893776-2c21-46fa-b3f9-9289f8e3e5c8-image.png

      I would like Codigo column to be stickied, how can I do this?

      Below the entire table code

      <template>
        <div>
          <q-table
            ref="mainTable"
            class="my-sticky-virtscroll-table"
            style="height: 800px"
            :data="data"
            :columns="columns"
            row-key="name"
            :selected-rows-label="getSelectedString"
            selection="multiple"
            :selected.sync="selected"
            virtual-scroll
            :pagination.sync="pagination"
            :virtual-scroll-sticky-size-start="48"
            :rows-per-page-options="[0]"
            :filter="filter"
            flat
            bordered=""
            @focusin.native="activateNavigation"
            @focusout.native="deactivateNavigation"
            @keydown.native="onKey"
          >
            <template v-slot:top-left>
              <q-input
                ref="mainSearchInput"
                debounce="0"
                v-model="filter"
                label="Búsqueda"
                filled
                bottom-slots
                clearable=""
                style="width:500px"
              >
                <template v-slot:hint
                  >Puede hacer búsquedas online con commandos.</template
                >
              </q-input>
            </template>
      
            <template v-slot:body-cell-qty="props">
              <q-td :props="props">
                <q-badge
                  :class="'(props.value < 1000) ? bg-red : bg-green'"
                  :label="props.value"
                />
              </q-td>
            </template>
      
            <template v-slot:body-cell-code="props">
              <q-td :props="props">
                <q-badge
                  :class="'!props.value ? bg-orange : bg-red'"
                  :label="props.value"
                />
              </q-td>
            </template>
          </q-table>
          <div class="q-mt-md">Selected: {{ JSON.stringify(selected) }}</div>
          <br />
        </div>
      </template>
      
      <script>
      import path from "path";
      import { remote } from "electron";
      
      export default {
        data() {
          return {
            navigationActive: false,
            filter: "",
            selected: [],
            pagination: {
              rowsPerPage: 0
            },
            columns: [
              {
                name: "code",
                required: true,
                label: "Código",
                align: "left",
                // field: row => row.name,
                field: "CODIGO",
                format: val => `${val}`,
                sortable: true
              },
              {
                name: "description",
                align: "left",
                label: "Descipción",
                field: "DESCRIPCION",
                sortable: true
              },
              { name: "qty", label: "Qty", field: "INVENT", align: "right" },
              { name: "codAlt", label: "Cod Alt", field: "COD.ALT.", align: "left" },
              {
                name: "desAlt",
                label: "Desc Alt",
                field: "DESC.ALT.",
                align: "left"
              },
              {
                name: "groups",
                label: "Grupo",
                field: "GRUPO",
                align: "left"
              },
              { name: "price", label: "Precio", field: "PRECIO", align: "right" },
              {
                name: "discount20",
                label: "20 %",
                field: "PRECIO",
                align: "right",
                sort: (a, b) => parseInt(a, 10) - parseInt(b, 10)
              }
            ],
            data: []
          };
        },
      
        methods: {
          getSelectedString() {
            return this.selected.length === 0
              ? ""
              : `${this.selected.length} record${
                  this.selected.length > 1 ? "s" : ""
                } selected of ${this.data.length}`;
          },
      
          activateNavigation() {
            this.navigationActive = true;
          },
      
          deactivateNavigation() {
            this.navigationActive = false;
          },
      
          onKey(evt) {
            if (
              this.navigationActive !== true ||
              [33, 34, 35, 36, 38, 40].indexOf(evt.keyCode) === -1 ||
              this.$refs.mainTable === void 0
            ) {
              return;
            }
      
            evt.preventDefault();
      
            switch (evt.keyCode) {
              case 36: // Home
                page = 1;
                index = 0;
                break;
              case 35: // End
                page = lastPage;
                index = rowsPerPage - 1;
                break;
              case 33: // PageUp
                page = currentPage <= 1 ? lastPage : currentPage - 1;
                if (index < 0) {
                  index = 0;
                }
                break;
              case 34: // PageDown
                page = currentPage >= lastPage ? 1 : currentPage + 1;
                if (index < 0) {
                  index = rowsPerPage - 1;
                }
                break;
              case 38: // ArrowUp
                if (currentIndex <= 0) {
                  page = currentPage <= 1 ? lastPage : currentPage - 1;
                  index = rowsPerPage - 1;
                } else {
                  index = currentIndex - 1;
                }
                break;
              case 40: // ArrowDown
                if (currentIndex >= lastIndex) {
                  page = currentPage >= lastPage ? 1 : currentPage + 1;
                  index = 0;
                } else {
                  index = currentIndex + 1;
                }
                break;
            }
      
            if (page !== this.pagination.page) {
              this.pagination = {
                ...this.pagination,
                page
              };
      
              this.$nextTick(() => {
                const { computedRows } = this.$refs.mainTable;
                this.selected = [
                  computedRows[Math.min(index, computedRows.length - 1)]
                ];
              });
            } else {
              this.selected = [computedRows[index]];
            }
          }
        },
      
        mounted() {
          // get file path
          const filePath = path.join(
            remote.app.getPath("home"),
            "/Dropbox/Sync/inventarioHL.json"
          );
      
          // load the File System to execute our common tasks (CRUD)
          var fs = require("fs");
      
          // read file content
          const fsData = fs.readFileSync(filePath, "utf-8");
      
          // parse text into json
          var jsonData = JSON.parse(fsData);
      
          // add entire data to table
          this.data = jsonData;
      
          // for (const x in jsonData) {
          //   console.log(x);
          // }
      
          console.log(jsonData[0]);
      
          // focus on q-input
          this.$refs.mainSearchInput.$el.focus();
        }
      };
      </script>
      
      <style lang="sass">
      .my-sticky-virtscroll-table
        /* height or max-height is important */
        height: 310px
      
        /* specifying max-width so the example can
          highlight the sticky column on any browser window */
        max-width: 1300px
      
        td:first-child
          /* bg color is important for td; just specify one */
          background-color: #fafafa !important
      
        tr th
          position: sticky
          /* higher than z-index for td below */
          z-index: 2
          /* bg color is important; just specify one */
          background: #fafafa
      
        /* this will be the loading indicator */
        thead tr:last-child th
          /* height of all previous header rows */
          top: 48px
          /* highest z-index */
          z-index: 3
        thead tr:first-child th
          top: 0
          z-index: 1
        tr:first-child th:first-child
          /* highest z-index */
          z-index: 3
      
        td:first-child
          z-index: 1
      
        td:first-child, th:first-child
          position: sticky
          left: 0
      </style>
      
      posted in Help
      F
      fenchai
    • Can't style QTable cell conditionally

      This is a simple template for a table I created with Quasar.

      :class="'(props.value < 1000) ? bg-red : bg-green'"
      I am not able to color each cell according to the number conditional and it keeps being false (In this case bg-green gets triggered on every cell). I checked that all cell’s typeOf is number.

      <template>
        <div class="q-pa-sm">
          <q-table
            ref="mainTable"
            class="my-sticky-virtscroll-table"
            style="height: 800px"
            :data="data"
            :columns="columns"
            row-key="name"
            :selected-rows-label="getSelectedString"
            selection="multiple"
            :selected.sync="selected"
            virtual-scroll
            :pagination.sync="pagination"
            :virtual-scroll-sticky-size-start="48"
            :rows-per-page-options="[0]"
            :filter="filter"
            flat
            bordered=""
            @focusin.native="activateNavigation"
            @focusout.native="deactivateNavigation"
            @keydown.native="onKey"
          >
            <template v-slot:top-left>
              <q-input
                ref="mainSearchInput"
                debounce="10"
                v-model="filter"
                label="Búsqueda"
                filled
                bottom-slots
                clearable=""
                style="width:500px"
              >
                <template v-slot:hint
                  >Puede hacer busquedas online con commandos.</template
                >
              </q-input>
            </template>
      
            <template v-slot:body-cell-qty="props">
              <q-td :props="props">
                <q-badge
                  :class="'(props.value < 1000) ? bg-red : bg-green'"
                  :label="props.value"
                />
              </q-td>
            </template>
      
            <template v-slot:body-cell-code="props">
              <q-td :props="props">
                <q-badge
                  :class="'props.value < 5 ? bg-orange : bg-red'"
                  :label="props.value"
                />
              </q-td>
            </template>
          </q-table>
          <div class="q-mt-md">Selected: {{ JSON.stringify(selected) }}</div>
        </div>
      </template>
      

      You can see here the Qty Column is always green and for some reason, Código Column is always true.

      This is how my table looks

      Below is my Script and Style Section.

      <script>
      import path from "path";
      import { remote } from "electron";
      
      export default {
        data() {
          return {
            navigationActive: false,
            filter: "",
            selected: [],
            pagination: {
              rowsPerPage: 0
            },
            columns: [
              {
                name: "code",
                required: true,
                label: "Código",
                align: "left",
                // field: row => row.name,
                field: "CODIGO",
                format: val => `${val}`,
                sortable: true
              },
              {
                name: "description",
                align: "left",
                label: "Descipción",
                field: "DESCRIPCION",
                sortable: true
              },
              { name: "qty", label: "Qty", field: "INVENT", align: "right" },
              { name: "codAlt", label: "Cod Alt", field: "COD.ALT.", align: "left" },
              {
                name: "desAlt",
                label: "Desc Alt",
                field: "DESC.ALT.",
                align: "left"
              },
              {
                name: "groups",
                label: "Grupo",
                field: "GRUPO",
                align: "left"
              },
              { name: "price", label: "Precio", field: "PRECIO", align: "right" },
              {
                name: "discount20",
                label: "20 %",
                field: "PRECIO",
                align: "right",
                sort: (a, b) => parseInt(a, 10) - parseInt(b, 10)
              }
            ],
            data: []
          };
        },
      
        methods: {
          getSelectedString() {
            return this.selected.length === 0
              ? ""
              : `${this.selected.length} record${
                  this.selected.length > 1 ? "s" : ""
                } selected of ${this.data.length}`;
          },
      
          activateNavigation() {
            this.navigationActive = true;
          },
      
          deactivateNavigation() {
            this.navigationActive = false;
          },
      
          onKey(evt) {
            if (
              this.navigationActive !== true ||
              [33, 34, 35, 36, 38, 40].indexOf(evt.keyCode) === -1 ||
              this.$refs.mainTable === void 0
            ) {
              return;
            }
      
            evt.preventDefault();
      
            switch (evt.keyCode) {
              case 36: // Home
                page = 1;
                index = 0;
                break;
              case 35: // End
                page = lastPage;
                index = rowsPerPage - 1;
                break;
              case 33: // PageUp
                page = currentPage <= 1 ? lastPage : currentPage - 1;
                if (index < 0) {
                  index = 0;
                }
                break;
              case 34: // PageDown
                page = currentPage >= lastPage ? 1 : currentPage + 1;
                if (index < 0) {
                  index = rowsPerPage - 1;
                }
                break;
              case 38: // ArrowUp
                if (currentIndex <= 0) {
                  page = currentPage <= 1 ? lastPage : currentPage - 1;
                  index = rowsPerPage - 1;
                } else {
                  index = currentIndex - 1;
                }
                break;
              case 40: // ArrowDown
                if (currentIndex >= lastIndex) {
                  page = currentPage >= lastPage ? 1 : currentPage + 1;
                  index = 0;
                } else {
                  index = currentIndex + 1;
                }
                break;
            }
      
            if (page !== this.pagination.page) {
              this.pagination = {
                ...this.pagination,
                page
              };
      
              this.$nextTick(() => {
                const { computedRows } = this.$refs.mainTable;
                this.selected = [
                  computedRows[Math.min(index, computedRows.length - 1)]
                ];
              });
            } else {
              this.selected = [computedRows[index]];
            }
          }
        },
      
        mounted() {
          // get file path
          const filePath = path.join(
            remote.app.getPath("home"),
            "/Dropbox/Sync/inventarioHL.json"
          );
      
          // load the File System to execute our common tasks (CRUD)
          var fs = require("fs");
      
          // read file content
          const fsData = fs.readFileSync(filePath, "utf-8");
      
          // parse text into json
          var jsonData = JSON.parse(fsData);
      
          // add entire data to table
          this.data = jsonData;
      
          // for (const x in jsonData) {
          //   console.log(x);
          // }
      
          console.log(jsonData[0]);
      
          // focus on q-input
          this.$refs.mainSearchInput.$el.focus();
        }
      };
      </script>
      
      <style lang="sass">
      .my-sticky-virtscroll-table
        /* height or max-height is important */
        height: 310px
      
        /* specifying max-width so the example can
          highlight the sticky column on any browser window */
        max-width: 1300px
      
        td:first-child
          /* bg color is important for td; just specify one */
          background-color: #fafafa !important
      
        tr th
          position: sticky
          /* higher than z-index for td below */
          z-index: 2
          /* bg color is important; just specify one */
          background: #fafafa
      
        /* this will be the loading indicator */
        thead tr:last-child th
          /* height of all previous header rows */
          top: 48px
          /* highest z-index */
          z-index: 3
        thead tr:first-child th
          top: 0
          z-index: 1
        tr:first-child th:first-child
          /* highest z-index */
          z-index: 3
      
        td:first-child
          z-index: 1
      
        td:first-child, th:first-child
          position: sticky
          left: 0
      </style>
      
      posted in Help
      F
      fenchai
    • Selecting on a single CheckBox in Table selects all rows.

      I am new to JS and Quasar so please pardon my ignorance.

      We can clearly see here that only 1 item is selected but visually all boxes are checked.
      940045c1-a281-4b15-a25d-eb9dbe883c23-image.png

      initially, I was thinking maybe row-key="name" is incorrect? but I have no idea how to test if this is correct or not.

      Below is the entire Page for the table.

      <template>
        <div>
          <q-table
            ref="mainTable"
            class="my-sticky-virtscroll-table"
            style="height: 800px"
            :data="data"
            :columns="columns"
            row-key="name"
            :selected-rows-label="getSelectedString"
            selection="multiple"
            :selected.sync="selected"
            virtual-scroll
            :pagination.sync="pagination"
            :virtual-scroll-sticky-size-start="48"
            :rows-per-page-options="[0]"
            :filter="filter"
            flat
            bordered=""
            @focusin.native="activateNavigation"
            @focusout.native="deactivateNavigation"
            @keydown.native="onKey"
          >
            <template v-slot:top-left>
              <q-input
                ref="mainSearchInput"
                debounce="0"
                v-model="filter"
                label="Búsqueda"
                filled
                bottom-slots
                clearable=""
                style="width:500px"
              >
                <template v-slot:hint
                  >Puede hacer búsquedas online con commandos.</template
                >
              </q-input>
            </template>
      
            <template v-slot:body-cell-qty="props">
              <q-td :props="props">
                <q-badge
                  :class="'(props.value < 1000) ? bg-red : bg-green'"
                  :label="props.value"
                />
              </q-td>
            </template>
      
            <template v-slot:body-cell-code="props">
              <q-td :props="props">
                <q-badge
                  :class="'!props.value ? bg-orange : bg-red'"
                  :label="props.value"
                />
              </q-td>
            </template>
          </q-table>
          <div class="q-mt-md">Selected: {{ JSON.stringify(selected) }}</div>
          <br />
        </div>
      </template>
      
      <script>
      import path from "path";
      import { remote } from "electron";
      
      export default {
        data() {
          return {
            navigationActive: false,
            filter: "",
            selected: [],
            pagination: {
              rowsPerPage: 0
            },
            columns: [
              {
                name: "code",
                required: true,
                label: "Código",
                align: "left",
                // field: row => row.name,
                field: "CODIGO",
                format: val => `${val}`,
                sortable: true
              },
              {
                name: "description",
                align: "left",
                label: "Descipción",
                field: "DESCRIPCION",
                sortable: true
              },
              { name: "qty", label: "Qty", field: "INVENT", align: "right" },
              { name: "codAlt", label: "Cod Alt", field: "COD.ALT.", align: "left" },
              {
                name: "desAlt",
                label: "Desc Alt",
                field: "DESC.ALT.",
                align: "left"
              },
              {
                name: "groups",
                label: "Grupo",
                field: "GRUPO",
                align: "left"
              },
              { name: "price", label: "Precio", field: "PRECIO", align: "right" },
              {
                name: "discount20",
                label: "20 %",
                field: "PRECIO",
                align: "right",
                sort: (a, b) => parseInt(a, 10) - parseInt(b, 10)
              }
            ],
            data: []
          };
        },
      
        methods: {
          getSelectedString() {
            return this.selected.length === 0
              ? ""
              : `${this.selected.length} record${
                  this.selected.length > 1 ? "s" : ""
                } selected of ${this.data.length}`;
          },
      
          activateNavigation() {
            this.navigationActive = true;
          },
      
          deactivateNavigation() {
            this.navigationActive = false;
          },
      
          onKey(evt) {
            if (
              this.navigationActive !== true ||
              [33, 34, 35, 36, 38, 40].indexOf(evt.keyCode) === -1 ||
              this.$refs.mainTable === void 0
            ) {
              return;
            }
      
            evt.preventDefault();
      
            switch (evt.keyCode) {
              case 36: // Home
                page = 1;
                index = 0;
                break;
              case 35: // End
                page = lastPage;
                index = rowsPerPage - 1;
                break;
              case 33: // PageUp
                page = currentPage <= 1 ? lastPage : currentPage - 1;
                if (index < 0) {
                  index = 0;
                }
                break;
              case 34: // PageDown
                page = currentPage >= lastPage ? 1 : currentPage + 1;
                if (index < 0) {
                  index = rowsPerPage - 1;
                }
                break;
              case 38: // ArrowUp
                if (currentIndex <= 0) {
                  page = currentPage <= 1 ? lastPage : currentPage - 1;
                  index = rowsPerPage - 1;
                } else {
                  index = currentIndex - 1;
                }
                break;
              case 40: // ArrowDown
                if (currentIndex >= lastIndex) {
                  page = currentPage >= lastPage ? 1 : currentPage + 1;
                  index = 0;
                } else {
                  index = currentIndex + 1;
                }
                break;
            }
      
            if (page !== this.pagination.page) {
              this.pagination = {
                ...this.pagination,
                page
              };
      
              this.$nextTick(() => {
                const { computedRows } = this.$refs.mainTable;
                this.selected = [
                  computedRows[Math.min(index, computedRows.length - 1)]
                ];
              });
            } else {
              this.selected = [computedRows[index]];
            }
          }
        },
      
        mounted() {
          // get file path
          const filePath = path.join(
            remote.app.getPath("home"),
            "/Dropbox/Sync/inventarioHL.json"
          );
      
          // load the File System to execute our common tasks (CRUD)
          var fs = require("fs");
      
          // read file content
          const fsData = fs.readFileSync(filePath, "utf-8");
      
          // parse text into json
          var jsonData = JSON.parse(fsData);
      
          // add entire data to table
          this.data = jsonData;
      
          // for (const x in jsonData) {
          //   console.log(x);
          // }
      
          console.log(jsonData[0]);
      
          // focus on q-input
          this.$refs.mainSearchInput.$el.focus();
        }
      };
      </script>
      
      <style lang="sass">
      .my-sticky-virtscroll-table
        /* height or max-height is important */
        height: 310px
      
        /* specifying max-width so the example can
          highlight the sticky column on any browser window */
        max-width: 1300px
      
        td:first-child
          /* bg color is important for td; just specify one */
          background-color: #fafafa !important
      
        tr th
          position: sticky
          /* higher than z-index for td below */
          z-index: 2
          /* bg color is important; just specify one */
          background: #fafafa
      
        /* this will be the loading indicator */
        thead tr:last-child th
          /* height of all previous header rows */
          top: 48px
          /* highest z-index */
          z-index: 3
        thead tr:first-child th
          top: 0
          z-index: 1
        tr:first-child th:first-child
          /* highest z-index */
          z-index: 3
      
        td:first-child
          z-index: 1
      
        td:first-child, th:first-child
          position: sticky
          left: 0
      </style>
      
      posted in Help
      F
      fenchai