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

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

    Framework
    7
    31
    3566
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      sontis last edited by sontis

      Hello.
      I’m using Quasar v1.0.0-beta.23.
      When I end edit content of the table cell in QPopupEdit I would like to save new value, but can not catch event “save”.
      The custom component that I’m building up is following:

      <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 :value="props.row.email" @save="(val, initialValue) => UpdateDocument(val, props.row, 'email')" buttons>
                    <q-input :value="props.row.email" count/>
                  </q-popup-edit>
                </q-td>
                ...
              </q-tr>
        </template>
      ...
      </q-table>
      ...
      methods: {
          UpdateDocument(val, row, column) {...}
      

      After running the app, I see in Vue.js devtools only the following events:
      …
      input $emit by<QInput>
      before-hide $emit by<QMenu>
      click $emit by<QBtn>
      hide $emit by<QPopupEdit>
      hide $emit by<QMenu>
      Can someone explain me what is going wrong here? Why the event “save” is not emitted?

      1 Reply Last reply Reply Quote 0
      • S
        sontis last edited by sontis

        When I use model of QPopupEdit and QInput as v-model=“myValue”, then event “save” emitted before “before-hide” event.
        I think this is a bug in the case model of QPopupEdit and QInput as :value="props.row.email"

        1 Reply Last reply Reply Quote 0
        • metalsadman
          metalsadman last edited by metalsadman

          @sontis dunno what you’re trying to do but save does get emitted using v-model.

          <q-td key="desc" :props="props">
                      {{ props.row.email }}
                      <q-popup-edit v-model="props.row.email" @save="(val, initialValue) => UpdateDocument(val, props.row, 'email')" buttons>
                        <q-input v-model="props.row.email" count/>
                      </q-popup-edit>
                    </q-td>
          ...
          

          https://codepen.io/metalsadman/pen/RmKeWL

          S 1 Reply Last reply Reply Quote 0
          • S
            sontis @metalsadman last edited by sontis

            @metalsadman
            I want to use Vuex data as the data source for QTable. In event @save I want to update data source by calling Vuex async action with invoke REST service. If I use v-model, then I have Vuex data modification error.
            I already had a issue about this.
            smolinari advised to use value in the case of Vuex.

            1 Reply Last reply Reply Quote 0
            • metalsadman
              metalsadman last edited by metalsadman

              @sontis you can invoke your api call on your @save event in this case your UpdateDocument method, it’s there you decide to commit it your store or revert the value back to original value in case of an error (i suggest passing the initialVal as well in your method). something like this.

              <q-popup-edit v-model="props.row.email" @save="(val, initialValue) => UpdateDocument(val, initialValue, props.row, 'email')" buttons>
              ....
              UpdateDocument(newVal, initVal, tableData, col) {
                //don't reflect change yet
                tableData[col] = initVal
                //call your api
                this.$axios...({
                  ....
                }).then(...{
                  //commit vuex
                  //commit value change
                  tableData[col] = newVal
                }).catch(...{
                  //revert to initial value on error 
                  //tableData[col] = initVal do nothing
                })
              }
              ...
              

              Updated the pen to kind of emulate this https://codepen.io/metalsadman/pen/RmKeWL.

              S 1 Reply Last reply Reply Quote 0
              • S
                sontis @metalsadman last edited by

                @metalsadman
                Your solution is not suitable for using vuex data source. In this case (v-model) I have vuex errors:

                vue.runtime.esm.js:619 [Vue warn]: Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside mutation handlers."
                (found in <Root>)
                
                vue.runtime.esm.js:1888 Error: [vuex] do not mutate vuex store state outside mutation handlers.
                    at assert (vuex.esm.js:87)
                    at Vue.store._vm.$watch.deep (vuex.esm.js:763)
                    at Watcher.run (vue.runtime.esm.js:4562)
                    at Watcher.update (vue.runtime.esm.js:4536)
                    at Dep.notify (vue.runtime.esm.js:730)
                    at Object.reactiveSetter [as name_ru] (vue.runtime.esm.js:1055)
                    at Proxy.set (vue.runtime.esm.js:1077)
                    at callback (countries.vue?d101:136)
                    at invokeWithErrorHandling (vue.runtime.esm.js:1854)
                    at VueComponent.invoker (vue.runtime.esm.js:2179)
                (found in <Root>)
                

                In my component I use Vuex ds like this:

                <q-table ...  :data="ds">
                ...
                </q-table>
                ...
                  computed: {
                    ...mapState({
                      ds: state => state.ds.dsCustomers
                    }),
                ...
                    ...mapActions({
                      updateDocument: 'ds/updateCustomer',
                    }),
                

                I also tested another case with the same Vuex errors:

                ...
                  computed: {
                    ds: {
                      get() {
                        return this.$store.state.ds.dsCustomers;
                      },
                      set(value) {
                        this.$store.commit('setDsCustomers', value);
                      },
                    },
                
                
                metalsadman 1 Reply Last reply Reply Quote 0
                • metalsadman
                  metalsadman @sontis last edited by metalsadman

                  @sontis you should make a local copy of your dsCustomers object that will be the one you pass in your q-tables data prop. still need more info probably make a codepen to show your minimal setup here.

                  1 Reply Last reply Reply Quote 0
                  • qyloxe
                    qyloxe last edited by

                    It looks as your app is big enough to use this:

                    https://github.com/vuex-orm/vuex-orm

                    In small use cases it is ok to create “spagetti” with those accessors/computed/events stuff, but in some point, the VueX querying is better. There are some other additional benefits: data models, normalization, easy synchronization.

                    S 1 Reply Last reply Reply Quote 0
                    • metalsadman
                      metalsadman last edited by

                      i use this a lot too https://github.com/maoberlehner/vuex-map-fields. i would definitely try that vuex-orm one on future project, and would’ve used it in the huge project that i’m currently working on but alas i found out about it quite too late :(, and my partner not too open for refactoring smh.

                      1 Reply Last reply Reply Quote 0
                      • reyhanoto
                        reyhanoto last edited by

                        Oh, that was my question too

                        1 Reply Last reply Reply Quote 0
                        • S
                          sontis @qyloxe last edited by

                          @qyloxe thanks for the advice to use vuex-orm. But this thing does not solve data processing problems in the QPopuEdit. Could you show a working example?
                          I see the following main problems in the QPopupEdit & Vuex:
                          In case of v-model, QPopupEdit (QInput) emits input event that causes Vuex data modification error;
                          In case of :value, QPopupEdit does not emit save event for correct Vuex data modification.

                          qyloxe 1 Reply Last reply Reply Quote 0
                          • qyloxe
                            qyloxe @sontis last edited by

                            @sontis if your problem is based on unability to update Vuex, then this library surely solves that:
                            https://vuex-orm.github.io/vuex-orm/guide/store/inserting-and-updating-data.html#inserts

                            if your problem is based on QPopupEdit component behaviour (events, model), then I do not have an opinion on that.

                            S 1 Reply Last reply Reply Quote 0
                            • S
                              sontis @qyloxe last edited by

                              @qyloxe
                              I think this is a QPopupEdit behaviour problem.
                              Anyway, @qyloxe, thanks for the advice.

                              1 Reply Last reply Reply Quote 0
                              • B
                                bfreed last edited by

                                I just ran into the same issue. I agree with @sontis - the recommendations for workarounds are great, but are definitely workarounds. If QPopupEdit emits a “save” event with v-model, it should also emit a “save” event when binding value instead. At the very least, when buttons are turned on and the save button is clicked… @sontis have you tried using a computed setter? https://itnext.io/anyway-this-is-how-to-use-v-model-with-vuex-computed-setter-in-action-320eb682c976 I haven’t tried it yet, but will as soon as I have time. It allows using v-model with Vuex, without adding an ORM package. Might trick the save event into happening

                                metalsadman 1 Reply Last reply Reply Quote 0
                                • metalsadman
                                  metalsadman @bfreed last edited by metalsadman

                                  @bfreed @sontis I don’t see why @save would trigger when you use :value in your q-input without using @input event on it, that’s a normal behavior https://vuejs.org/v2/guide/forms.html. Updated my pen using :value on both QPopupEdit and QInput https://codepen.io/metalsadman/pen/arLYOe. further reading about vuex https://vuex.vuejs.org/guide/forms.html#form-handling.

                                  B S 2 Replies Last reply Reply Quote 0
                                  • B
                                    bfreed @metalsadman last edited by

                                    @metalsadman Thank you for the codepen!!
                                    I didn’t get that @save only fires if the value has changed. Makes sense now.
                                    Before writing my actions and mutations, I was trying to test with console logs, but since I wasn’t modifying my state (yet), the saves weren’t firing at all.
                                    @sontis: I’m grabbing the @save event on the q-popup-edit and calling an action to write to my API. On the q-input inside the popup, I’m grabbing @input and calling a mutation to set the vuex store.
                                    Now that the state is actually changing, q-popup-edit fires the @save event when I click the “set” button, and the API only gets hit then, not on every keystroke.

                                    1 Reply Last reply Reply Quote 0
                                    • S
                                      sontis @metalsadman last edited by

                                      @metalsadman thank you for the codepen and the explanation. The code (with using @input event) now works, BUT:
                                      I have the following data processing GUI -> Vuex -> REST Api -> DB Store.
                                      And I have now the messy code, because,

                                      • In @input event handler in QInput need update ONLY Vuex store. I do not want to invoke REST api after each key press. For this I have mutation and in during editing in the QPopupEdit the Vuex Store is unsynchronized with the DB Store. At this time, all GUI elements using this data will show an incorrect value.
                                      • In @save event handler in the QPopupEdit need send data by REST and if response OK then update Vuex Store.
                                      • In@cancel event handler in the QPopupEdit need recover Vuex Store back.
                                        The worst is Vuex Store is unsynchronized with the DB Store at some point. All GUI elements (which used this data) will not be displayed correctly.
                                      1 Reply Last reply Reply Quote 0
                                      • metalsadman
                                        metalsadman last edited by metalsadman

                                        @sontis it’s there in my example, @save event you have access to the initialValue and the newValue, you only commit the newValue when all goes well and can still revert to initialValue if something fails. like i said this has nothing to do with vuex or whatever data source you are using, the idea is the same. It’s a pretty solid component tbh and I don’t think in this case there’s a need for something to change, since clearly the functionalities are working as they should be.

                                        S 1 Reply Last reply Reply Quote 0
                                        • S
                                          sontis @metalsadman last edited by sontis

                                          @metalsadman
                                          Your codepen consists code:

                                          <q-input :value="props.row.name" dense autofocus counter @input="v => {props.row.name = v}"></q-input>
                                          

                                          If you will be use Vuex Store as the data source for your QTable, then each key press in the QPopupEdit will be modificate Vuex Store data without vuex mutation. This will cause an error

                                          vue.runtime.esm.js:1888 Error: [vuex] do not mutate vuex store state outside mutation handlers.
                                          

                                          See posts above.
                                          Therefore, in the case of QPopupEdit + Vuex + Rest Api + DB I have the messy code.

                                          B 1 Reply Last reply Reply Quote 0
                                          • metalsadman
                                            metalsadman last edited by metalsadman

                                            @sontis hard to figure what you are actually doing in your vuex mutation, like i said in earlier post copy it first locally then that local data is what you should feed to your QTable’s data props then on your QPopupedit’s save event is where you call your actual vuex mutation/action. Per your thread’s title, there’s no issue there.

                                            About the vuex issue, would take some time for me to exactly emulate what’s wrong unless you provide a minimal pen of how you were doing it. I will try tho…

                                            S 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post