Skip to content
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

Add validate property #2

Closed
simonepri opened this issue Feb 26, 2018 · 23 comments
Closed

Add validate property #2

simonepri opened this issue Feb 26, 2018 · 23 comments
Labels
enhancement New feature or request

Comments

@simonepri
Copy link
Contributor

simonepri commented Feb 26, 2018

Proposal to add a validate property:

validate: (Function || Async Function) Receive the user input and answers of a chain.

Should return true if the value is valid, and an error message (String) otherwise.
If false is returned, a default error message is provided.

To do this we need to add a way to render errors messages.

API Usage Example:

validate: (input, answers) => {
  if (input === 'invalid') return 'The answer is invalid.';
  return true;  // Proceed to the next prompt of the chain if any.
}
@terkelg
Copy link
Owner

terkelg commented Feb 26, 2018

It's super important for me to keep the package really tight - without too many features or dependencies. What would the use case be for this?

I normally just do multiple prompts() and do validation after each.

That being said I've thinking about doing a message and split prompt.

@simonepri
Copy link
Contributor Author

simonepri commented Feb 26, 2018

The main difference of doing the validation after the prompt is that you can't show live errors to users.

An example from inquirer:
image

Also it allows user to not have complicate logic to handle response rejection.

@lukeed
Copy link
Collaborator

lukeed commented Feb 27, 2018

Personally, I'd call this a maybe. As you've both mentioned, this requires an entirely new error-like module that might go beyond the scope of @terkelg's intentions.

A quick (and still manageable) way around this is to process prompts one at a time & then "validate" them on the onSubmit hook. You could choose to exit the prompt with an error (stdout.write('Reason'); return true) or display the same prompts definition, with an updated initial or message key.

function isCustom(val) {
  // return true if I consider valid
}

let defs = [
  {
    type: 'text',
    name: 'foobar',
    isValid: isCustom
  }, { 
    // ... etc
  }
];

function onSubmit(obj, val) {
  obj.isValid(val) && defs.shift(); // if valid, remove item
}

async function run() {
  if (!defs.length) return 'done';
  return await prompts(defs[0], { onSubmit }).then(run);
}

await run();

Not sure if the above will work 😆 Quick psuedo'ing

@simonepri
Copy link
Contributor Author

It just feel too complicated to handle this manually for each prompt.
Also because the error is supposed to disappear after a valid input is provided.

@terkelg
Copy link
Owner

terkelg commented Feb 27, 2018

I'll take a look at this for a version v0.2. Feel free to add a PR

@terkelg terkelg added enhancement New feature or request maybe Might add this in the future labels Feb 27, 2018
@yoavmmn
Copy link
Contributor

yoavmmn commented Feb 28, 2018

Wait, whats wrong with options.onSubmit? It's built right into the API.
I think the only drawback is that you can't force the user to enter the expected input.

@yoavmmn
Copy link
Contributor

yoavmmn commented Feb 28, 2018

Here's a little demonstration of the capabilities of options.onSubmit.

const prompts = require('prompts');

function isInputHiOrHey(greeting = '') {
  return greeting === 'hi' || greeting === 'hey';
}

// a recursive function that checks user's input just for the prompt named greeting
function checkInput(prompt, answer) {
  if (prompt.name === 'greeting') {
    if (!isInputHiOrHey(answer)) {
      console.log('Please enter a valid greeting.');
      prompts(prompt, { onSubmit: checkInput })
    }
  }
}

prompts({
  type: 'text',
  name: 'greeting',
  message: 'What\'s your greeting?'
}, {
  onSubmit: checkInput
});

@lukeed
Copy link
Collaborator

lukeed commented Feb 28, 2018

@yoavmmn That's essentially what my example is doing 😆 I agree, I think it's sufficient.

In order to display an error message, you could attach an onError key to each prompt, then change mine to:

function onSubmit(obj, val) {
  obj.isValid(val) ? defs.shift() : obj.onError();
}

Or handle all of that inside the isCustom function:

function isCustom(val) {
  if (val > 100) return true;
  console.log('ERROR MESSAGE');
  //=> returns undefined --> falsey
}

@yoavmmn
Copy link
Contributor

yoavmmn commented Feb 28, 2018

@lukeed I have no idea how I missed your comment. Maybe because it's midnight already over here 😅

@tunnckoCore
Copy link

Just realized that the whole thing is that we need prop like onSubmit option but per question object. Then we can do anything from validate to required and etc.

@marcghorayeb
Copy link

Validate property would be nice yep 👍

@terkelg
Copy link
Owner

terkelg commented Mar 6, 2018

After #43 all prompts have a onSubmit and onAbort. It's in master but not yet released or documented. I'm still open for implementing some nice visuals for this later.

Focus right now is to get v0.1.5 out the door.

@dsevillamartin
Copy link

Sorry for the bump.

Is this feature still being considered?
Or at least, some method to make a custom implementation of it easier?

I would like to replace inquirer with this great module 🙂

@tunnckoCore
Copy link

@datitisev it was while ago.. Can't you use onSubmit to implement it?

@dsevillamartin
Copy link

@olstenlarck I haven't coded anything with prompts yet, and as this issue is still open, I thought maybe the end result was similar to validation (after reading all the comments), but not exactly.
Maybe I misread them, apologies if I did.
I'll see if I can implement it when I have the time.

@tunnckoCore
Copy link

I didn't tried onSubmit still either, but.. In glance looks it seems it would work.

@terkelg
Copy link
Owner

terkelg commented Aug 4, 2018

onSubmit is different from what @datitisev is asking for. I still want and need the filter myself. The feature is still being considered.

@terkelg terkelg removed the maybe Might add this in the future label Aug 14, 2018
@terkelg terkelg added this to the v1.0.0 milestone Aug 14, 2018
@terkelg
Copy link
Owner

terkelg commented Aug 18, 2018

validate option is added in v1.0.0 branch for Number and Text prompt.

const response = await prompts({
    type: 'number',
    name: 'value',
    message: 'How old are you?',
    validate: value => value < 18 ? `Nightclub is 18+ only` : true
});

Please give it a test run if you like @datitisev @lukeed @marcghorayeb

@dsevillamartin
Copy link

dsevillamartin commented Aug 18, 2018

@terkelg Works great! 🙂 Thanks!

Edit: Not sure if it is a result from this change, but when the onCancel function returns true, it still exists.
image
image

@terkelg
Copy link
Owner

terkelg commented Aug 18, 2018

@datitisev is that a single prompt or a prompt chain?

@dsevillamartin
Copy link

@terkelg A single prompt.

  let onCancel = prompt => {
    console.log('Never stop prompting!');
    return true;
  }

  const response = await prompts({
      type: 'text',
      name: 'email',
      message: 'What\'s yar email?',
  }, { onCancel });

  console.log(response);

@terkelg
Copy link
Owner

terkelg commented Aug 18, 2018

onCancel is not preventing you from canceling a single prompt, it controls whether the prompt chain should cancel or continue. If you have an array of prompts you'll see it either continue or break the chain based on the onCancel return value.

@terkelg
Copy link
Owner

terkelg commented Aug 23, 2018

Coming in #80

@terkelg terkelg closed this as completed Aug 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants