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

Ability to have dependent fields & options within repeatable groups #96

Closed
Mosnar opened this issue May 29, 2020 · 9 comments
Closed

Ability to have dependent fields & options within repeatable groups #96

Mosnar opened this issue May 29, 2020 · 9 comments
Labels
suggestions welcome Looking for suggestions on a proposal

Comments

@Mosnar
Copy link

Mosnar commented May 29, 2020

Describe the new feature you'd like
It's not uncommon for a field to be dependent on another field's value. This is no-problem using Vue's computed properties; however, if I need to have a repeatable group of such fields, there isn't a way to for me to use the current group's model as context for the values of my dropdown.

For example, consider a form where I can order coffees. I would have a grouped input for selecting the beverage type and it's options. If I have a selection for "Cream?" with the values Yes and No, I might then want an input for "How much cream?" to appear when the user selects "Yes".

Perhaps I'm missing something, but it doesn't seem like there's an easy way to do this right now.
Using VueFormGenerator, you were able to pass a function into the "options" parameter of a Select field. The first argument of that function would be the current state of that particular group's model. Additionally, fields have a "visible" attribute that would also accept a boolean or similar callback. This gives you the ability to contextually hide a field.

What percentage of vue-formulate users would benefit?
70%

@Mosnar Mosnar added the feature request New feature or request label May 29, 2020
@justin-schroeder
Copy link
Member

Hey 👋 Are your questions specifically in the context of form generation?

@justin-schroeder
Copy link
Member

Hmm actually I think I’m following. This is a good question....thanks for the detailed example. Let me think on this....

@Mosnar
Copy link
Author

Mosnar commented May 29, 2020

Hey, thanks for the great work on this project and the quick response! I actually just figured out a way to do it. But to answer your question, no it's not a generated form. I'm working on an order form where a user can add some products. They start with a product category, then they're shown a product model in that category.

I realized you can actually get the information from the context and do what I need to do, but it's a little verbose/janky. Here's what I ended up with:

<FormulateInput
        type="group"
        name="products"
        :repeatable="true"
        label="Products"
        add-label="+ Add Product"
        validation="required"
        :value="[{}]"
        #default="{ name, index }"
>
    <FormulateInput
            name="productCategory"
            :options="productCategories"
            type="select"
            label="Product Category"
            validation="required"
    />
    <FormulateInput
            v-if="model[name][index] && model[name][index].productCategory"
            name="productStyle"
            :options="getProductStyles(model[name][index])"
            type="select"
            label="Product Style"
            validation="required"
    />
</FormulateInput>

I need to have a default value in my group field, even if it's just a single empty object, otherwise it throws an undefined index error.

@justin-schroeder justin-schroeder added suggestions welcome Looking for suggestions on a proposal and removed feature request New feature or request labels May 30, 2020
@justin-schroeder
Copy link
Member

Hey @Mosnar. You're pretty much right on here. Because it's repeatable you have to use functions instead of computed props to calculate the values of the internals unless you abstract the contents of default group slot into it's own component. I just worked up a little example this conditional repeatable functionality as an example of how I would solve this:

https://codepen.io/justin-schroeder/pen/NWGQbKV

I think the only feature-addition we could potentially add to make this a tad easier is have something like a groupValues exposed on the context object of the default slot. That makes it a bit easier, because you don't have to access the data by the index, but it ultimately requires passing the data into a method to compute the correct values. Open to suggestions on that one.

I'll leave this open for now to help anyone else stumbling on it.

@Mosnar
Copy link
Author

Mosnar commented May 31, 2020

Thanks for the example! There's one other caveat with this approach I ran into that can be a little weird that I wanted to document here for others. When you update the source for a dependent field (ie, Select "Coffee" and then "Drip") then change it to "Tea", you'll notice the model will still have the invalid "Drip" value. For me, this caused issues because certain fields were supposed to be hidden and I was only checking to see if a value was set on the dependent property, it would show the dropdown without any options. To get around this, I had to introduce an additional check into my v-if to ensure there were options available.

I expanded on your example to show the issue. Try selecting "Coffee" -> "Drip" then change it from "Coffee" to "Tea" and you'll notice the "Leave me room for cream" field still shows up due to the malformed model:
https://codepen.io/mosnar/pen/oNjKMMv

The hacky solution is of course to simply check up the chain of dependencies, but this can get pretty messy pretty quickly if you have a lot of fields and you still have an invalid model.

@justin-schroeder
Copy link
Member

I think this is working as intended (it would apply to non-grouped fields too) actually, but you're right that it could be confusing. The issue is that at a library level we don't want to assume the model’s value should be equal to an available option since that takes power away from implementers. But I could be convinced this behavior should be changed for select or box inputs since the library will always control those internals.

A pretty easy way to solve this edge case in user-land right now is to just perform a check on the options to make sure the current value is selected. Here's a forked codepen:

https://codepen.io/justin-schroeder/pen/BajBWWm

@Mosnar
Copy link
Author

Mosnar commented Jun 1, 2020

I agree that this is working as intended (but perhaps not as expected.) A side-effect of that is some weird behavior where the input model and the form model can fall out of sync. In your CodePen, try this:

  1. Select Coffee
  2. Select Drip
  3. Change "Coffee" to "Tea"
  4. Change "Tea" back to "Coffee"
    See that "Drip" is already pre-selected but the model doesn't have a "variant" property.

I get the feeling that these types of issues are fundamentally related to the core problem in my initial post where additional conditions and logical complexity are needed to ensure the form is in a valid state. I don't have any suggestions at this point, but I think there's a good solution out there that would solve all/most of these quirks at once.

P.S. I see you're from Charlottesville! Greetings from Blacksburg!

@justin-schroeder
Copy link
Member

:) Howdy neighbor 👍

Yeah, in that codepen I made the variety option go away intentionally by setting the value to undefined you could choose to set it to an actual value, or the first option, if that better suits the needs of the author.

And I totally agree that the default behavior of leaving behind an un-available option is definitely not an expected behavior. What’s your opinion on what the expected behavior is? Sometimes that's tricky to figure out.

@davidebigpicture
Copy link

And, I actually will use dependent fields in a generated fashion, where a DB is storing hundreds of different forms for different clients.

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

No branches or pull requests

3 participants