lljj-x / vue-json-schema-form

基于Vue/Vue3,Json Schema 和 ElementUi/antd/iview3/naiveUi 等生成 HTML Form 表单,用于活动编辑器、h5编辑器、cms等数据配置;支持可视化生成表单Schema 。 Generate a form using Vue/Vue3, Json Schema and ElementUi/antdv/iview3/naiveUi
https://form.lljj.me/
Apache License 2.0
2.01k stars 418 forks source link

Inject model to ui-widget #261

Closed clabnet closed 1 year ago

clabnet commented 1 year ago

I have this schema

...
  "properties": {
    "item": {
      "title": "Item",
      "type": "string",
      "ui:widget": "PopSelect"
    },
...

where PopSelect is :

<script setup lang="ts">
  const options: any = 
  [
    {       label: 'Test 1',  value: 'song0'    },
    {       label: 'Test 2',  value: 'song1'    }
  ]
  const value = ref(null)
</script>
<template>
  <div class="w-90">
    <n-popselect v-model:value="value" :options="options">
      <n-button>{{ value || 'Popselect' }}</n-button>
    </n-popselect>
  </div>
</template>

I should be avoid to set options into PopSelect internally. Can I pass options to PopSelect from external ? Where I do set v-model to set option value's ? Thank's in advance.

BossHogg97 commented 1 year ago

Hi, i'm working with Vue3 and NaiveUI.

I'm trying to pass model to custom widget that i integrate inside form. I read the documentation and i saw that is possible to connect the model of the form with the one of custom widget. Here my code:

First the custom component that i want to put in the form

<script setup lang="ts">
  import { SelectOption } from 'naive-ui'

  const modelValue = ref(null)

  type Props = {
    selectOptions: any
  }

  const props = defineProps<Props>()

  function doSelectionUpdate(option: SelectOption) {
    console.log('Selected values: ', option)
  }
</script>

<template>
  <div class="w-90">
    <n-select v-model:value="modelValue" :options="$props.selectOptions" multiple placeholder="Please select" @update:value="doSelectionUpdate" />
  </div>
</template>

Here the schemaUI code:

schemaUI.value = {
    multipleChoicesList: {
      'ui:widget': shallowRef(multipleCombo),
      'ui:selectOptions': options,
      'ui:modelValue': hotShearFilter,
      'ui:options': {
        width: '100%',
      },
    },
  }

I don't know how to link hotshearFilter (the model of Vue JSON schema form) with n-select

Thanks

lljj-x commented 1 year ago

I have this schema

...
  "properties": {
    "item": {
      "title": "Item",
      "type": "string",
      "ui:widget": "PopSelect"
    },
...

where PopSelect is :

<script setup lang="ts">
  const options: any = 
  [
    {       label: 'Test 1',  value: 'song0'    },
    {       label: 'Test 2',  value: 'song1'    }
  ]
  const value = ref(null)
</script>
<template>
  <div class="w-90">
    <n-popselect v-model:value="value" :options="options">
      <n-button>{{ value || 'Popselect' }}</n-button>
    </n-popselect>
  </div>
</template>

I should be avoid to set options into PopSelect internally. Can I pass options to PopSelect from external ? Where I do set v-model to set option value's ? Thank's in advance.

Use ui:xxx to pass the options parameter,Custom widget component must support vue3 v-model:value

<script setup lang="ts">
const props = defineProps({
  options: Array
})
</script>
<template>
  <div class="w-90">
    <n-popselect v-bind="$attrs" :options="props.options">
      <n-button>{{ $attrs.value || 'Popselect' }}</n-button>
    </n-popselect>
  </div>
</template>

Schema use ui:options pass params

 "properties": {
    "item": {
      "title": "Item",
      "type": "string",
      "ui:widget": "PopSelect",
     "ui:options": [
        {"label": "Test 1",   "value": "song0"    },
        { "label": "Test 2",  "value": "song1"    }
      ]
    },
lljj-x commented 1 year ago

Hi, i'm working with Vue3 and NaiveUI.

I'm trying to pass model to custom widget that i integrate inside form. I read the documentation and i saw that is possible to connect the model of the form with the one of custom widget. Here my code:

First the custom component that i want to put in the form

<script setup lang="ts">
  import { SelectOption } from 'naive-ui'

  const modelValue = ref(null)

  type Props = {
    selectOptions: any
  }

  const props = defineProps<Props>()

  function doSelectionUpdate(option: SelectOption) {
    console.log('Selected values: ', option)
  }
</script>

<template>
  <div class="w-90">
    <n-select v-model:value="modelValue" :options="$props.selectOptions" multiple placeholder="Please select" @update:value="doSelectionUpdate" />
  </div>
</template>

Here the schemaUI code:

schemaUI.value = {
    multipleChoicesList: {
      'ui:widget': shallowRef(multipleCombo),
      'ui:selectOptions': options,
      'ui:modelValue': hotShearFilter,
      'ui:options': {
        width: '100%',
      },
    },
  }

I don't know how to link hotshearFilter (the model of Vue JSON schema form) with n-select

Thanks

modelValue use computed emit update, reference vue3 component v-model :https://vuejs.org//guide/components/v-model.html

custom component like this:

const modelValue = computed({
    get() {
        return props.modelValue;
    },
    set(value) {
        emit('update:modelValue', value);
    }
});
BossHogg97 commented 1 year ago

modelValue use computed emit update, reference vue3 component v-model :https://vuejs.org//guide/components/v-model.html

custom component like this:

const modelValue = computed({
    get() {
        return props.modelValue;
    },
    set(value) {
        emit('update:modelValue', value);
    }
});

Hi, thanks for the answer. I tried this method and the model is correctly pass and updated. I have now a problem with schema validation because the ui:widget is defined inside the json with "type": "string". And my custom component doesn't return a string but an array of string. How can i solve this validation problem? Following my code.

This is the json schema

{
  "type": "object",
  "properties": {
    "multipleChoicesList": {
      "title": "hotShearType",
      "type": "string"
    }
  }
}

This is the code where i define the custom component:

 schemaUI.value = {
    multipleChoicesList: {
      'ui:widget': shallowRef(multipleCombo),
      // Passing props via ui:xxx where xxx is the name of the prop inside custom component
      'ui:selectOptions': options,
      'ui:modelValue': modelFilter,
      'ui:options': {
        width: '100%',
      },
    },
  }

Finally this is the component with your suggestions:

<script setup lang="ts">
  import { NSelect } from 'naive-ui'

  type Props = {
    selectOptions: any
    modelValue: any
  }

  const emit = defineEmits(['update:modelValue'])
  const props = defineProps<Props>()

  const modelValue = computed({
    get() {
      return props.modelValue
    },
    set(value) {
      emit('update:modelValue', value)
    },
  })
</script>

<template>
  <div class="w-90">
    <n-select v-model:value="modelValue" :options="props.selectOptions" multiple placeholder="Please select" />
  </div>
</template>

I also tried to convert the value returned from n-select as string but it doesn't work. image

Thanks!

lljj-x commented 1 year ago

@BossHogg97 set schema to array type

{
  "type": "object",
  "properties": {
    "multipleChoicesList": {
          "type": "array",
          "title": "A multiple choices list",
          "items": {
              "type": "string"
          }
    }
  }
}
BossHogg97 commented 1 year ago

Thank you so much! Your component is very powerful!