Skip to content

Provides ability to parse dot string json objects into the schema property. #164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 0 commits into from

Conversation

jmverges
Copy link
Contributor

The root object must be declared into the window object to be able to do this without any kind of eval.

this means
window.VueFormGenerator = VueFormGenerator;
if schema validator is like

"VueFormGenerator.validators.string"
to avoid to instantiate the whole object we could simply do

window.MyValidators = VueFormGenerator.validators
and later into the schema string

MyValidators.string

Fixes #163

@cristijora
Copy link
Collaborator

Interesting approach. This heavily relies on the naming convention though.
Can you add some unit tests for this case ?

@jmverges
Copy link
Contributor Author

There you go

@cristijora
Copy link
Collaborator

From my side this looks fine. Let's see what @icebob and @lionel-bijaoui think about this.
I would add maybe a console warn if your string parsing check fails.

if(isString(transformedValidator)){
let chunks = transformedValidator.split(".");
let root = chunks.shift();
transformedValidator = objGet(window[root], chunks.join("."));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add some warning here that such a validator cannot be found and some tip on what to do.
Don't know how the default error looks for this case but I guess it's "ReferenceError x is not defined" which is not very helpful I guess.

@lionel-bijaoui
Copy link
Member

lionel-bijaoui commented Mar 21, 2017

@cristijora I'm only a collaborator, only @icebob decide what's merged or not.
I don't know what @icebob think exactly about it, but so far, the compiled js are only included with a new tag version.
I prefer to have them at every PR so it is easier to test (like you did).

@jmverges Thank you very much for your fast work !
Can you describe the exact usage of your PR so we can add it to the documentation ?
What are the limitation/options ?
Can I use it with my own validator (as long as they are available in window) ?
Thanks !

@jmverges
Copy link
Contributor Author

Hi @lionel-bijaoui, you are welcome. The exact usage is described in #163.

Basically I'm storing into the database some schemas which includes validators. Those are stored and returned as string. Later on I use that schema to generate a form. For the documentation, I would add an example talking about AJAX with mounted() for populate the schema property.

The limitation is: you need to can access globally to the Validators object. For this you need to add it to window object like here:

    import VueFormGenerator from "vue-form-generator";
    Vue.use(VueFormGenerator);
    window.VueFormGeneratorValidators = VueFormGenerator.validators;

then in the schema.validators you need to use "VueFormGeneratorValidators.string" for example.

Respect to using your own validator, I'm not aware if this can be done at the moment, but if this is posible, yes, you still can.

This pull request is not modifying the current implementation, just adding a little feature ;)

@jmverges
Copy link
Contributor Author

I just added the throw error suggestion and a test to check it from @cristijora.

Let me know what you think guys 👍

@@ -5,6 +5,9 @@ function checkIfValidatorIsAStringAndConvertToObject(validator) {
if(isString(transformedValidator)){
let chunks = transformedValidator.split(".");
let root = chunks.shift();
if(typeof window[root] == "undefined"){
throw "[VueFormGenerator] window["+root+"] is not defined. For using dot notation json strings in validators, look at the documentation.";
Copy link
Collaborator

@cristijora cristijora Mar 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer es6 string interpolation as it looks better and more clear.

throw `[VueFormGenerator] window[${root}] is not defined. If you want to use strings when defining a validator please see link here`

By the way what happens if you try to register your validator like this:
validator: "validators.string" Is it going to work ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would ask you, did you defined window.validators = VueFormGenerator.validators?

Copy link
Collaborator

@cristijora cristijora Mar 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind. Got it wrong the first time
This works
https://jsfiddle.net/z11fe07p/1058/
The usage however for the implicit case would be

import VueFormGenerator from "vue-form-generator";
Vue.use(VueFormGenerator);
window.VueFormGenerator= VueFormGenerator;

See fiddle where VueFormGenerator is assigned by default to the window object.

@icebob
Copy link
Member

icebob commented Mar 21, 2017

Hi guys,

Sorry, but I think, we don't have to implement this function for vfg, because it is a custom problem. And @jmverges can do this convertion in his app inside after the axios returned the schema

axios.get(url).then(function (response) {
	that.schema = response.data;

	this.schema.fields.forEach(field => {
		if (typeof field.validator == "string") {
			// .. do the convertion from string to function
		}
	})
});

@jmverges
Copy link
Contributor Author

Hi @icebob,

yes, this could be solved also in that way. However, I would like to think my use case is enough common and this little feature could help other users in the same situation.

Cheers.

@icebob
Copy link
Member

icebob commented Mar 21, 2017

Ok, but not this format. Because it's more complex.

  • don't set validators to window, because abstractField can import it.
  • don't use "VueFormGenerator.validator.string". Use a shorthand mode e.g.: "string" or "number". Only the name of validator function. It's more simple & universal. It can be an array of string if you are using multiple validators.
  • don't throw error. If the schema definition is wrong, the error is important to developer, not to end-user. So use console.warn instead.

So example schema:

{
	fields: [
		{
			type: "input",
			inputType: "text",
			validator: "string"
		},
		{
			type: "input",
			inputType: "number",
			min: 1,
			max: 10,
			validator: ["required", "number"]
		},
	]
}

and the converter code:

import validators from "../utils/validators";

function convertValidator(validator) {
	if (isString(validator)) {
		if (validators[validator] != null)
			return validators[validator];
		else {
			console.warn(`'${validator}' is not a validator function!`);
			return null; // caller need to handle null
		}
	}
	return validator;
}

Could you change your PR?

@jmverges
Copy link
Contributor Author

Ok, I will change it tomorrow. However, I would like to ask if vfg is able to use a different validator library or custom validators created by the user as in that case this feature wouldn't be compatible with those scenarios.

@lionel-bijaoui
Copy link
Member

don't throw error. If the schema definition is wrong, the error is important to developer, not to end-user. So use console.warn instead.

I'm going to change one of my PR (#152) 😅 (fieldChecklist.vue line 60 and 75, and fieldRadios.vue line 39 and 54)

@icebob
Copy link
Member

icebob commented Mar 21, 2017

Different validator library is not supported, but you can extend with custom validators.
E.g.:

import VueFormGenerator from "vue-form-generator";
Vue.use(VueFormGenerator);

// Add my custom even validator
VueFormGenerator.validators.even = function(value, field) {
	if (value % 2)
		return [`${value} is not even!`];
};

I don't tested the code, maybe contains syntax errors

@jmverges
Copy link
Contributor Author

Ok, I'm a bit new with Vue. Could those validators be defined in a different file from the .vue file/component where are used?

@icebob
Copy link
Member

icebob commented Mar 21, 2017

Yes, but you need to import the file before using vfg in your template.

@jmverges
Copy link
Contributor Author

And once is imported, I would need to extend the vfg validators with my own, am I right?

@icebob
Copy link
Member

icebob commented Mar 21, 2017

Sample:

my-validators.js

import { validators } from "vue-form-generator";

// Add my custom even validator
validators.even = function(value, field) {
	if (value % 2)
		return [`${value} is not even!`];
};

main.js

import VueFormGenerator from "vue-form-generator";
Vue.use(VueFormGenerator);

import "./my-validators.js";

@jmverges
Copy link
Contributor Author

Thank you. I will give it a try tomorrow morning and commit the changes to the PR.

Cheers.

@imoon
Copy link

imoon commented Mar 22, 2017

@jmverges, for additional input, I ran into exactly the same issue a while ago. I'm storing my schemas in postgres as jsonb which requires strict JSON meaning the validators must be strings. I'm using Django as my backend so my work around was to parse the JSON and remove quotes around the validator before sending to client. I've never liked having to do that so I'm very pleased this has been added to vfg.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants