jarvelov / vue-form-json-schema

Create forms using JSON schema. Bring your components!
https://jarvelov.gitbook.io/vue-form-json-schema/
353 stars 53 forks source link

Use model value for another component as prop #73

Open AlexanderStoffers opened 4 years ago

AlexanderStoffers commented 4 years ago

Hi there,

we would like to use the actual model value (that is an array) from one component as input for a custom multi select component.

Of course we could do it easily in the code, but if we would do so, we would loose the majjor advantage of vue-form-json-schema in our usecase.

Is there any way to "reference" a model value to props/attrs of another component within the (static) ui schema?

Thank you in Advance Alex

jarvelov commented 4 years ago

Hi Alexander,

I'm sorry that it's taken me a while to get back to you. If I understand you correctly you want to do something like this:

Peek 2020-09-17 00-01

(I quickly threw together a custom multi select which doesn't preserve the selected values when updated, however regular component will not have this issue and I hope the functionality is demonstrated sufficiently regardless)

Okay, so in this example we will work with this component, it is terrible but it is easy to understand:

// main.js
// register global component 'custom-select'
Vue.component('custom-select', {
  name: 'custom-select',
  props: ['options', 'value'],
  template: `
    <select multiple :value="value" @change="onChange">
      <option v-for="option in options">
        {{option}}
      </option>
    </select>
  `,
  methods: {
    onChange() {
      const selected = this.$el.querySelectorAll('option:checked');
      const values = Array.from(selected).map(element => element.value);

      this.$emit('change', values);
    },
  },
});
// MyForm.vue
uiSchema: [
  // Select 1
  {
    component: 'custom-select',
    model: 'availableOptions', // This sets what property in the form model is passed to this component's 'value' prop and will be updated when the 'change' event is emitted
    fieldOptions: {
      on: ['change'],
      props: {
        options: ['Cat', 'Dog', 'Rabbit'],
      },
    },
  },
  // Select 2
  {
    component: 'custom-select',
    model: 'selectedOptions', , // This sets what property in the form model is passed to this component's 'value' prop and will be updated when the 'change' event is emitted
    valueModel: 'availableOptions', // This overrides what property in the form model will be passed to this component, the default is to pass it to the 'value' prop
    valueProp: 'options', // This overrides the prop to which the field's model will be passed and sets it to 'options', this prop will receive the value of 'valueModel' if it is set, or else it will receive the normal 'model' value
    fieldOptions: {
      on: ['change'],
    },
  }
]

However, unfortunately this isn't available yet, but good news, it was simple to add and I should be able to release it tomorrow in v2.8.4.

AlexanderStoffers commented 4 years ago

That sounds perfect! Looking forward to the 2.8.4 release!

Thanks Alex

jarvelov commented 4 years ago

Hi again,

v2.8.4 has now been released. Check it out and let me know if you run into any issues.

AlexanderStoffers commented 4 years ago

Hi there,

i just tested the new version. First of all...the described behaviour works :-)

In my specific case i´m missing the posibility to use the whole model i´m injecting into vue-form-json-schema because i´m creating the name by several fields out of one form:

model = {key1: "Hi", key2: "Peter", key3: "" }

In the ui i can only refer to the keys but i would have to refer to the whole model:

valueProp: "options" valueModel: "$root model?!"

Is there an ability to refer to the "root model"?

Best Regards Alex

jarvelov commented 4 years ago

I guess there's no technical constraints to add this functionality, but it might be a foot gun as it might cause a lot of re-renders. I'll look into adding this feature sometime this week.

jarvelov commented 4 years ago

Hi again. I just released v2.8.5 with the feature to pass down the entire form's model to a field with valueModel: true. I hope this lets you achieve what you're after. Let me know how things work out, cheers.

AlexanderStoffers commented 4 years ago

Hey,

that sounds good. Will check later!

Thank you in Advance, Alex