xpepermint / vue-rawmodel

RawModel.js plugin for Vue.js v2. Form validation has never been easier!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Shared client and server side validation models

travisstaloch opened this issue · comments

Thank you so much for sharing this great library!

Is it possible to share models between client and server? I'm working on a vue front end with a feathers/express back end where I want to have a single source of validation. In order to share models, should I just make a models folder in the project root directory (along side app and src directories which contain vue and feathers apps)? This project has a single package.json and webpack.config(s) at the project root directory.

I'm about to try this out. Can anyone provide any advice for getting this to work? I see that the vue-example has its models in the client src directory. Not sure if that app is doing server-side validation using those models. Is this the recommended method? I will post my results back here soon. Thank you.

Hey @travisstaloch. This package provides only a wrapper around RawmodelJS which adds VueJS reactivity to Model. Reactivity is only needed for reactive forms (reactive form validation). RawmodelJS works on the server and in the browser thus you can share your main logic between the server and the browser.

// client
import {ReactiveModel} from 'vue-rawmodel';
class User extends ReactiveModel {
  // main logic here
}

// server
import {Model} from 'rawmodel';
class User extends Model {
  // main logic here
}

Ok thanks. I didn't realize that its only a wrapper for reactivity.

Is it possible to put the validation logic in one place then like this?

class User extends ReactiveModel {
  constructor(data = {}) {
    defineValidations(this)
  }
}
class User extends Model {
  constructor(data = {}) {
    defineValidations(this)
  }
}

That should do the trick.

Is it possible to ignore a field defined in a model? I have SignupModel < ReactiveModel with fields email, password, and confirmPassword which shares validation definitions with SignupModelServer < Model as described above. I want to ignore the confirmPassword field on the server. Is there an easy way to achieve this?

Just have multiple models.

I was hoping to avoid that. I'm thinking I can use a condition() in the password2 validation which does some sort of check to switch it off, maybe check if typeof this !== 'SignupModelServer'

I think I found a solution: obj isInstanceOf ReactiveModel is more generic and can be reused in different models. Thought I would share to help out as it also shows a working defineValidator to compare with another field in the model which took a little bit of research to get working.

signup.js

import { ReactiveModel } from 'vue-rawmodel'
import { Model } from 'rawmodel'

export class SignupModel extends ReactiveModel {
  constructor(data = {}) {
    super(data)
    defineValidations(this, data)
  }
}

export class SignupModelServer extends Model {
  constructor(data = {}) {
    super(data)
    defineValidations(this, data)
  }
}

function defineValidations(that, data) {
  that.defineField('email', {
    type: 'String',
    validate: [
      {
        validator: 'presence',
        message: 'is required'
      },
      {
        validator: 'stringEmail',
        message: 'is invalid'
      }
    ]
  })

  that.defineField('password', {
    type: 'String',
    validate: [
      {
        validator: 'presence',
        message: 'is required'
      },
      {
        validator: 'stringLength',
        message: 'is too short or too long (%{min} to %{max} characters)',
        min: 4,
        max: 33
      }
    ]
  })

  that.defineValidator('equalsPassword', v => {
    return v === that.getField(['password']).value
  })

  that.defineField('password2', {
    type: 'String',
    validate: [
      {
        validator: 'presence',
        message: 'is required',
        condition() {
          return that instanceof ReactiveModel
        }
      },
      {
        validator: 'equalsPassword',
        message: 'is different from password',
        condition() {
          return that instanceof ReactiveModel
        }
      }
    ]
  })

  that.populate(data)
}