[SOLVED] QPopupEdit in QTable with Vuex data source - Do not emitted save event.



  • @metalsadman
    But then I have to have a local copy data source and synchronize it with the vuex data source.
    Why then need vuex? 🙂
    Sorry, I am not a native English speaker. Maybe I got a mistake with the thread’s title



  • @sontis you should mark as solved concerning the thread title since there’s nothing wrong with the event. your real issue was mutating your store, anyway here’s what i got https://codesandbox.io/s/q306jwnjx6 click “home” -> 'vuex table`, check the consoles, dunno if this is what you did, i would still suggest making a local copy and run your action/mutation @save event since that shows in vue devtools and is the vuex way of doing it.



  • @metalsadman thanks for good example.
    If you set Vuex strict mode in the “…/store/index.js”:

      const Store = new Vuex.Store({
        strict: true,
        modules: {
          vuexDataTable
        }
      });
    

    then you see vuex errors after editing fields (check codesandbox console)
    ![screenshot]
    vuex-err.png



  • @sontis yep that’s why do my suggestion to copy it in local and do the mutation in the events. then in the watcher re assigned it to the local data. you should try to figure it out imo. the example is there to get you started.



  • @metalsadman
    “…suggestion to copy it in local…”
    In this case, I don’t need Vuex 🙂 (data duplication/synchronization)
    In Vuex Guide Form Handling recommends:
    “…The “Vuex way” to deal with it is binding the <input>'s value and call an action on the input or change event…”
    But the problem is that the quasar does not allow to mutate the properties of vuex storage objects.



  • @sontis You can avoid the vuex error by calling a mutation instead of modifying the props inline.
    Mine looks like this:
    @input="v => { setPendingRowState( {myVar: v, handle: props.row.handle} ); }

    Where “setPendingRowState” commits a mutation:
    setPendingRowState: function(payload) {
    this.$store.commit(“progressReview/updatePendingProgress”, payload);
    }

    Obviously it doesn’t fix your concerns about being out of sync with the db, but hopefully it helps with the error anyway



  • @sontis well that’s the way to do it, beside this is normal behavior for vuex in strict mode coz you cannot simply mutate an array it’s entirety. what you can do is normalize your data in your vuex state, and then make a local copy map it to be an array (coz QTable data prop only accept an array), and in your mutation function you will have to filter it like an id to target that specific element in your state. keep on reading and you’ll get same answers :). you keep repeating it’s a quasar issue when it’s not :(.

    anyway updated the sandbox using lodash https://codesandbox.io/s/q306jwnjx6.



  • @metalsadman thank you.
    I found another solution.
    I create the local buffer for v-model of the QPopupEdit. In @show event I fill this buffer from Vuex data and in @save event I invoke REST Api “update” method and change Vuex data. It seems so much easier. I have code like this:

    <q-table ...  :data="ds">
    ...
      <template v-slot:body="props">
            <q-tr :props="props">
              <q-td key="desc" :props="props">
                {{ props.row.email }}
                <q-popup-edit v-model="popupEditData"
                    @show="() => showPopup(props.row, 'name')"
                    @save="(val, initval) => onUpdateDocument(val, props.row, 'name')"
                    buttons>
                  <q-input v-model="popupEditData" counter/>
                </q-popup-edit>
              </q-td>
              ...
            </q-tr>
      </template>
    ...
    </q-table>
    ...
    export default {
      data() {
        return {
          popupEditData: '',
        };
    
      computed: {
        ...mapState({
          ds: state => state.ds.dsCustomers
        }),
    
      methods: {
        ...mapActions({
          getDocuments: 'ds/getCustomers',
          updateDocument: 'ds/updateCustomer',
        }),
    
        showPopup(row, col) {
          this.popupEditData = row[col];
        },
    
        onUpdateDocument(val, row, col) {
          this.setLoading(true);
          const updatedRow = extend({}, row);
          updatedRow[col] = val;
          const res = this.updateDocument(updatedRow);
          res.then((response) => {
            ...
            this.getDocuments();
          })
            .catch((err) => {
              ...
            })
            .finally(() => {
              this.setLoading(false);
            });
        },
    


  • Just so i understand. I also had the problem with “do not mutate vuex store state outside mutation handlers” and i now have a local baseFilter in data:

     data() {
        return {
           baseFilter: {},
    ...
    

    and then i update vuex in watch like this:

    methods: {
        ...mapActions('filter', ['setPostsFilter']),
       ...
    
     watch: {
        baseFilter: {
          handler() {
            this.setPostsFilter({
              open: this.baseFilter.open,
              deleted: this.baseFilter.deleted,
              post_type: this.baseFilter.post_type,
              search: this.baseFilter.search
            })
          },
          deep: true
        }
      },
    

    and then i get the state from vuex on mount like this:

    computed: {
        ...mapState('filter', ['postsFilter'])
    ......
    
    mounted() {
        this.baseFilter = this.postsFilter
    ...
    

    is this an okay solution @metalsadman ?



  • @PeterQF yeah if somehow it shows error or the state gets modified by your local changes, you deep copy the state before you assign it to local.


Log in to reply