Manweill / swagger-axios-codegen

swagger client to use axios and typescript
MIT License
306 stars 83 forks source link

Validation attributes #50

Closed fairking closed 4 years ago

fairking commented 5 years ago

Would like to see something to be able to generate validation attributes among with model classes. It would be really cool.

My view model looks like this: image

I got my api like this: image

I am thinking about to implement client validation using vuelidate or VeeValidate

Is there any way to somehow translate model attributes using swagger-axios-codegen and use them in validation? Any ideas?

fairking commented 5 years ago

Maybe it could be something like this?

ISwaggerOptions = {
  ...
  renderValidationModel: [ true | false ],
  ...
}

codegen output:

export class RoleVm {
  name?: string;
  description?: string;
  static ValidationModel() {
    return {
      name: {
        required,
        minLength: 1,
        maxLength: 50
      },
      description: {
        maxLength: 150
      }
    }
  }
}

It is interesting how easy we can bind the validation model with the vuelidate or VeeValidate.

vuelidate example (not sure it will work):

import { required, minLength, maxLength } from 'vuelidate/lib/validators'

export default {
  data () {
    return {
      model: new RoleVm(),
    }
  },
  validations: RoleVm.ValidationModel()
}

vee-validate example (not sure it will work):

<template>
<validation-provider rules="validations.name" v-slot="{ errors }">
  <input v-model="model.name" name="name" type="text" />
  <span>{{ errors[0] }}</span>
</validation-provider>
</template>

<script>
import { ValidationProvider, extend } from 'vee-validate';
import { required, minLength, maxLength } from 'vee-validate/dist/rules';

extend('required', { ...required, message: 'The {_field_} field is required' });
extend('minLength', { ...minLength, message: 'The {_field_} field must not be less than {_min_} characters' });
extend('maxLength', { ...maxLength, message: 'The {_field_} field must not be more than {_max_} characters' });

new Vue({
  el: '#app',
  components: {
    ValidationProvider
  },
  data: () => ({
    model: new RoleVm(),
    validations: RoleVm.ValidationModel()
  }),
});
<script>
Manweill commented 4 years ago

This is good idea. Welcome PR

Manweill commented 4 years ago

@denis-pujdak-adm-it

Would you like to add an example to Readme?

fairking commented 4 years ago

Hi @Manweill I am trying to integrate my project with vuelidate. Ones I done with it I'm gonna add some small example to the readme file.

fairking commented 4 years ago

I did some work in my project. I decided that the only rules I need in javascript are actually required and maxlength. I am not going to use vuelidate or any other similar approach. Everything else is covered by server side validation. My axios receives the 400 errors with the following model [{ field: 'name', message: 'The value must contain only letters and numbers' }]. The model in my api is:

[Required]
[StringLength(50)]
[RegularExpression(@"^([a-zA-Z0-9])+$", ErrorMessage = "The value must contain only letters or numbers")]
public string Name { get; set; }

Where the [Required] and [StringLength] are covered by swagger-axios-codegen. All other validations are server side validations and I am happy with that approach. If anyone would like to include more validation rules into the swagger-axios-codegen feel free to create a PR.

My vuejs approach with swagger-axios-codegen validationModel: Mixin:

Vue.mixin(clientValidations());

function clientValidations() {
    return {
                data() {
            return {
                vModel: {},
            };
        },
        methods: {
            function isRequired(fieldName: string): boolean {
                            return (vModel && vModel[fieldName] && vModel[fieldName].required === true);
                        },
                        function maxLength(fieldName: string): number {
                            return (vModel && vModel[fieldName] && vModel[fieldName].maxLength ? vModel[fieldName].maxLength : 4000);
                        }
        },
    };
}

Component.vue

<template>
    <div>
        <label for="name">Name</name>
    <input id="name" type='text' v-model="model.name" :required="isRequired('name')" :maxlength="maxLength('name')" />
        <validation-message v-model="serverSideValidation('name')"></validation-message>
    </div>
</template>

<script lang="ts">
    import Vue from "vue";

    export default Vue.extend({
                data() {
                    return {
                        model: new FooFormVm(),
                    }
                },
                created() {
                    this.vModel = FooFormVm.validationModel;
                },
    });
</script>

But I cannot see any problem with using vuelidate or vee-validate. You can easy translate the validationModel into the rules your approach requires. Please let me know what do you think guys.

Manweill commented 4 years ago

@fairking this issue can close?

fairking commented 4 years ago

Yes you can close. The most important things are covered. If someone needs more validation he/she can raise a new issue.