vue-formulate icon indicating copy to clipboard operation
vue-formulate copied to clipboard

Add a hook mechanism for manipulating the input model (Original: Ability to mask input values).

Open paulogr opened this issue 4 years ago • 21 comments

Describe the new feature you'd like

Many times we have to mask input values for better UX.

VueFormulate already have really good features and be able to mask a value is the only missing feature that makes me add an extra dependency to handle my forms.

Today I use vue-the-mask (https://github.com/vuejs-tips/vue-the-mask) but it seen dead, doesn't have any activity from the maintainer and a lot of good contributors PR to get merged.

What percentage of vue-formulate users would benefit?

80%

Let's talk about it.

paulogr avatar Apr 16 '20 17:04 paulogr

I've wondered about adding support for something like this too. I think my approach to this would be to add this kind of support via a VueFormulate plugin. I like the syntax that vue-the-mask was using with a simple prop. It would take a very slight shift to the internal model to make it work, but nothing dramatic.

Ideally it could use something like https://nosir.github.io/cleave.js/ under the hood.

justin-schroeder avatar Apr 16 '20 17:04 justin-schroeder

Putting this on the roadmap for 2.x.x. The only implementation in formulate itself will be a "mask" prop and config option that takes a function and will be used as in the model setter, but we'll leave it up to external libraries like cleave to do the actual masking.

justin-schroeder avatar May 22 '20 18:05 justin-schroeder

Support for Money https://github.com/vuejs-tips/v-money https://github.com/autoNumeric/autoNumeric https://github.com/probil/v-mask

frankdors avatar Jun 15 '20 14:06 frankdors

Upvote for this 👍

vue-the-mask and v-money are both by @neves, so it may share some standardisations that can allow an easier integration with vue-formulate – but both projects haven't received commits for years and have a lot of pending pull requests 😢

text-mask is very popular, but also not maintained anymore. They recommend imaskjs, which appears to be a nice option and has an official Vue implementation.

I didn't know about cleave.js – as suggested by @justin-schroeder, but it has a lot of favs and a Vue example. Did you guys already worked with this?

hmaesta avatar Jul 01 '20 12:07 hmaesta

Hey, I've implemented a solution to have masks with https://imask.js.org/ with FormulateForm or FormulateInput.

You can check working demos here: https://codesandbox.io/s/vue-formulate-extended-masks-9i1wy?file=/src/App.vue. Currently available from vue-formulate-extended (with peer depedencies, careful). Repo

I'd be happy to discuss how this could become a cleaner solution @justin-schroeder ;)

gahabeen avatar Jul 01 '20 16:07 gahabeen

+1 for @gahabeen's solution

atharva3010 avatar Jul 08 '20 14:07 atharva3010

I like this idea of creating a modelHook (similar to the nodeHook and componentHook we discussed and I implemented in `vue-formulate-extended).

We could build tiny plugins based on it like a vue-formulate-mask for ex or do you see these like features you'ld want to have in-house? @justin-schroeder

gahabeen avatar Jul 08 '20 21:07 gahabeen

I've just made a PR (#166) to have a modelHook on FormulateInput (available through a schema with FormulateForm too).

It'll be super easy to have the mask feature once it's pushed! I made an example for a mask/format feature in a test there: https://github.com/wearebraid/vue-formulate/blob/b0dfc0d23c6caff9dd619b208522487ab126b58c/test/unit/FormulateForm.test.js#L828-L876

gahabeen avatar Jul 09 '20 10:07 gahabeen

@paulogr @hmaesta @frankdors Text Mask is now part of the - now stabilized - plugin vue-formulate-extended.

Check it out in a live demo: https://codesandbox.io/s/text-mask-04dh5?file=/src/components/Sandbox.vue

gahabeen avatar Jul 10 '20 19:07 gahabeen

I'm going to focus this thread around this idea @gahabeen and I have been kicking around of hooks as a first class citizen in Vue Formulate. Here's a proposed syntax:

Vue.use(VueFormulate, {
  hooks: {
    model: [], // used for masking, or mutating
    schema: [], // used for mutating an entire schema
    schemaNode: [] // used for mutating individual schema nodes
    // ... other things we think up
  }
})

Then on an individual input, we would also allow inline hooks:

<FormulateInput
  model-hook="myFn"
/>

Hooks would function using a middleware pattern, allowing for a stack of functions to work together. Also, to be clear, these hooks are not intended to be used by your average beginner. I think having easy to use plugins will be a must-have in order to expose a higher-level. A hook would look a lot like what @gahabeen has above (in the meantime, use his module!). Here's a simple one:

function numeric (model, next) {
  return isNaN(model) ? next(0) : next(parseInt(model, 10))
}

Still open to suggestions on this API.

justin-schroeder avatar Jul 11 '20 02:07 justin-schroeder

Not sure which hook this would apply to, but a use-case where this may be applicable is being able to set html form attributes globally. In our case, we're using standard html forms so every form needs method="post", but there are certain circumstances where things like enctype="multipart/form-data”, and `accept-charset="UTF-8" may be globally necessary as well. Perhaps hooks would help in this instance?

Also, since these are standard traditional forms, we're having to attach @submit="submit()" to every form instance. Would be great to use hooks to standardize this into every form instance hits this method without explicitly setting.

chasegiunta avatar Jul 11 '20 20:07 chasegiunta

@justin-schroeder I like the more middleware-like implementation you suggested.

Also I'ld recommend something like function hook(value, context, next) where context contains specific data depending on the hook being used.

gahabeen avatar Jul 14 '20 10:07 gahabeen

This functionality would also be really useful for GraphQL. We're trying to replace a custom form setup with VueFormulate and we're running into #161. In our current code, we are using .number modifier to ensure our inputs are type cast at the form rather than all of the places we have to use them. If we could do something like cast all fields that are number validated, that would be helpful.

bbugh avatar Jul 20 '20 22:07 bbugh

I'm still really in love with this feature, but now that we have a clear roadmap for 3.0 it feels like something that belongs inthat re-write rather than patched into 2.x feature set, re-tagged for 3.0

justin-schroeder avatar Nov 23 '20 15:11 justin-schroeder

hey @gahabeen I sent a PR fixing the compatibility of the newer version of vue formulate..

Review it, please https://github.com/gahabeen/vue-formulate-extended/pull/18

CavalcanteLeo avatar Apr 28 '21 18:04 CavalcanteLeo

Hi there! Any updates of this issue? Or we see this feature only in v3?

adinvadim avatar Aug 05 '21 13:08 adinvadim

@adinvadim this will only be available in the next major release as it requires a underlying re-write to do well.

justin-schroeder avatar Aug 05 '21 15:08 justin-schroeder

Okey, thank you! May be there is workaround or examples for add mask to common input?

adinvadim avatar Aug 05 '21 18:08 adinvadim

You can checkout vue-formulate-extended. Looks like @CavalcanteLeo submitted a PR, but I think @gahabeen added some of these features to Vue Formulate using that plugin

justin-schroeder avatar Aug 05 '21 19:08 justin-schroeder

Thank you! Im just looking vue-formulate-extended.

@gahabeen is there the plugin with this functionality? Or while everything in vue-formulate-extendete repository?

adinvadim avatar Aug 05 '21 19:08 adinvadim

Has this been resolved yet? "vue-formulate-extended" doesn't seem to work upon install, and it looks like a dead/paused project. How can we add masks to these inputs?

Love the project btw.

adamelevate avatar Feb 12 '22 17:02 adamelevate