how to use enum in apollo-client?

11,173

Solution 1

As the error message is suggesting, Schema type definitions not allowed in queries., you can't add an enum definition in an operation document (ExecutableDefinition). You can only have operations (query, mutation, or subscription), or fragments definitions. That is, this is invalid:

enum OrderTypes {
  FULL_BUY
  PINK_BUY
}

mutation createOrderMutation {
  ...
}

If you want to define a local enum on your client, you can use the typeDefs property during ApolloClient initialization:

const client = new ApolloClient({
  cache,
  typeDefs: gql`
    enum OrderTypes {
      FULL_BUY,
      PINK_BUY
    }
  `,
});

And then you'll be able to see the OrderTypes enum on client-side introspection (i.e Apollo extension).

Pay attention to the client-side highlight: if you try to send a request with this enum for a non-client field (i.e without the @client directive) and it makes through your server, you'll get a schema error saying that the enum type does not exist, unless you define it on your backend.

Solution 2

Prerequisites:

We must define < SomeEnumType > in our GraphQL schema (server side, no client configuration needed)

Let's assume we have defined:

enum SomeEnumType {
    OPTION1,
    OPTION2,
    OPTION3
}

We also must configure our Apollo Client in appropriate way ans connect it with the GraphQL API.

Then on client side:

export const OUR_MUTATION = gql`
    mutation ourMutation($foo: SomeEnumType){
        ourMutation(foo: $foo){
            bar
        }
    }    
`

Only doing this, you can pass enum as a variable in your query or mutation. For example using useMutation hook we can now mutate as follows:

const [ourMutation] = useMutation(OUR_MUTATION, {
        variables: {
            foo: "OPTION2"
        },

Since our type definition in gql tag equals with definition in Schema, GraphQL recognizes our variable as an enum type despite of that we give it as a string.

If we want pass enum to our variables using typescript enums we can do it as follows:

enum SomeEnumType {
    OPTION1 = 0,
    OPTION2 = 1,
    OPTION3 = 2
}

const [ourMutation] = useMutation(OUR_MUTATION, {
        variables: {
            foo: SomeEnumType[SomeEnumType.OPTION1]
        },

Solution 3

Now I'm stuck with the same problem. I found a solution like this. Maybe it works the way you can solve your problem.

import { Component, OnInit } from '@angular/core';
import { MatSnackBar } from '@angular/material';
import { Router } from '@angular/router';
import { slugify } from '../../helpers/slugify';
import { SEOService } from '../../services/seo.service';

import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MustMatch } from '../../helpers/must-match-validator';

import { MAT_MOMENT_DATE_FORMATS, MomentDateAdapter } from '@angular/material-moment-adapter';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';

import { CreateUserInput, RegisterPageRegisterGQL, Roles } from '@generated-types';

@Component({
  selector: 'app-register',
  templateUrl: './register.component.html',
  styleUrls: [
    './register.component.scss'
  ],
  providers: [
    // The locale would typically be provided on the root module of your application. We do it at
    // the component level here, due to limitations of our example generation script.
    { provide: MAT_DATE_LOCALE, useValue: 'tr-TR' },

    // `MomentDateAdapter` and `MAT_MOMENT_DATE_FORMATS` can be automatically provided by importing
    // `MatMomentDateModule` in your applications root module. We provide it at the component level
    // here, due to limitations of our example generation script.
    { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
    { provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS },
  ],
})

export class RegisterComponent implements OnInit {
  registerForm: FormGroup;
  submitted = false;
  error: any;
  genders: any = ['Kadın', 'Erkek', 'Belirtmek İstemiyorum'];

  user: CreateUserInput;

  constructor(
    public snackBar: MatSnackBar,
    private router: Router,
    private seoService: SEOService,
    private formBuilder: FormBuilder,
    private _adapter: DateAdapter<any>,
    private registerPageRegisterGQL: RegisterPageRegisterGQL,
  ) { }

  // convenience getter for easy access to form fields
  get f() { return this.registerForm.controls; }

  ngOnInit() {
    // datepicker locale
    this._adapter.setLocale('tr');
    // seo service
    this.seoService.addDefaultMetaTags();
    this.seoService.meta.updateTag({ name: 'robots', content: 'noindex' });
    this.seoService.addTitle('Kayıt Ol | kitaphub');
    // form validator
    this.registerForm = this.formBuilder.group({
      userName: ['', Validators.required],
      email: ['', [Validators.required, Validators.email]],
      firstName: ['', Validators.required],
      lastName: ['', Validators.required],
      password: ['', [Validators.required, Validators.minLength(6)]],
      confirmPassword: ['', Validators.required],
      gender: ['', Validators.required],
      dateOfBirth: ['', Validators.required],
      acceptTerms: [false, Validators.requiredTrue]
    }, {
      validator: MustMatch('password', 'confirmPassword')
    });
  }

  async onSubmit() {
    console.log('onSubmit');
    this.submitted = true;

    // stop here if form is invalid
    if (this.registerForm.invalid) {
      return;
    }

    // display form values on success
    alert('SUCCESS!! :-)\n\n' + JSON.stringify(this.registerForm.value, null, 4));

    this.registerPageRegisterGQL.mutate({
      user: {
        userName: this.registerForm.value.userName,
        email: this.registerForm.value.email,
        slug: slugify(this.registerForm.value.userName),
        firstName: this.registerForm.value.firstName,
        lastName: this.registerForm.value.lastName,
        password: this.registerForm.value.password,
        gender: this.registerForm.value.gender,
        role: Roles.MEMBER
      }
    }).subscribe(({ data }) => {
      console.log('got data:', data);
      this.openSnackBar('KAYIT İŞLEMİ TAMAMLANDI');
    }, (error: any) => {
      this.handleError(error);
      console.log('there was an error sending', error);
    });
  }

  onReset() {
    this.submitted = false;
    this.registerForm.reset();
  }

  handleError(error: any) {
    this.error = error.message;
  }

  openSnackBar(text: string) {
    return this.snackBar.open(text, 'X', { horizontalPosition: 'right', verticalPosition: 'top', duration: 3000 });
  }

}

Share:
11,173
lidashuang
Author by

lidashuang

coding

Updated on June 14, 2022

Comments

  • lidashuang
    lidashuang almost 2 years

    the enum define in OrderTypesEnum.gql

    enum OrderTypes {
      full_buy
      pink_buy
    }
    

    import OrderTypesEnum.gql file

    import OrderTypes from '@/graphql/OrderTypesEnum.gql'`
    

    but, How to get enum in code ?

    I use OrderTypes.full_buy get some error:

       self.$apollo.mutate({
            mutation: createOrder,
            variables: {
              subjectId: self.subject.id,
              types: OrderTypes.full_buy
            }
          })
    
    Mutation createOrderMutation error: Invariant Violation: Schema type definitions not allowed in queries. Found: "EnumTypeDefinition"
    

    the inspect of OrderTypes type enum

    enter image description here