Search code examples
javascriptvuejs2apollovue-apollo

How to access the state of apollo (GraphQL) query triggered by click event


In vue application I need to run gql query when user clicks the button. So the HTML part has the button:

<div 
  :id="'button-' + id"
  class="more-button" 
  @click="showDetails(id)">&nbsp;</div>

And the corresponding function is doing some debug console.log and firing the this.apollo.query. The problem is that I can see in the console all console.log output, so the function executes, but none of the hooks: error/result/watchLoading happens. At least I do not see anything in the console output.

showDetails(item) {
  console.log("before: " + msid);
  let msid = this.position.instrument.morningstarId;
  this.xxx = msid;
  this.$apollo.query({
    query: GET_INSTRUMENT,
    variables: {
      morningstarId: this.position.instrument.morningstarId
    },
    result({ data }) {
      console.log("L data: " + JSON.stringify(data));
    },
    error(error) {
      alert("L We've got an error!" + JSON.stringify(error));
    },
    watchLoading(isLoading) {
      console.log("L isLoading: " + isLoading);
    }
  });
  console.log("after: " + msid);
}

When I move all the content of this.$apollo.query to apollo section in the component, all works OK. So the working code after the change looks like this:

...
data() {
  return {
    instrument: null
  };
},
  apollo: {
    instrument: {
      query: GET_INSTRUMENT,
      variables() {
        return {
          morningstarId: this.position.instrument.morningstarId
        };
      },
      result({ data }) {
        console.log("G data: " + JSON.stringify(data));
      },
      error(error) {
        alert("G We've got an error!" + JSON.stringify(error));
      },
      watchLoading(isLoading) {
        console.log("G isLoading: " + isLoading);
      }
    }
  },
computed
...

But I do not want to have this query called when the component is built. I want to have it called only from the function. I am not interested in using the skip() method as a solution like described here.

The question is: what am I doing wrong, that any of the watchLoading/error/result hooks logs anything to the console?

There is neither error, nor warning in the console. But if force error in example by changing:

  this.$apollo.query({
    query: GET_INSTRUMENT,

to

  this.$apollo.query({
    q_uery: GET_INSTRUMENT,

then I see in the console:

QueryManager.js?96af:473 Uncaught Error: query option is required. You must specify your GraphQL document in the query option.

So I am sure that apollo is working with the query. But i have no idea how to access the result or state.


Solution

  • The solution is to treat the query like Promise and use then method on it.

    As described here: The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.

    So instead of the code I was using:

    showDetails(item) {
      console.log("before: " + msid);
      let msid = this.position.instrument.morningstarId;
      this.xxx = msid;
      this.$apollo.query({
        query: GET_INSTRUMENT,
        variables: {
          morningstarId: this.position.instrument.morningstarId
        },
        result({ data }) {
          console.log("L data: " + JSON.stringify(data));
        },
        error(error) {
          alert("L We've got an error!" + JSON.stringify(error));
        },
        watchLoading(isLoading) {
          console.log("L isLoading: " + isLoading);
        }
      });
      console.log("after: " + msid);
    }
    

    The working code to access the results and handle the error is:

    showDetails(item) {
        this.$apollo
          .query({
            query: GET_INSTRUMENT,
            variables: {
              morningstarId: this.instrumentObj.instrument.morningstarId,
              freq: this.chartFrequency
            }
          })
          .then(data => {
            this.instrument = data.data.instrument;
            this.loading = data.loading;
            this.networkStatus = data.networkStatus;
            this.generatePastChart();
          })
          .catch(error => {
            this.error = error;
            alert("E " + error);
          });
    
    }
    

    then method registers a callback function with retrieved data object as an input parameter.
    catch handles the failure