1

I have code below:

...
var label_key_map = { a: "1", b: "2", c: "3", d: "4" }
render: (h) => {
  var form_data = {}
  for (let key in label_key_map) {
    var form_item = h(
      'FormItem',
      {props: {prop: key}},
      [h('Input', {props: {type: "text", vModel: "form_data.key"}})]
    )
  }

In the for-loop I want to bind the form_data.a, form_data.b, form_data.c to every Input.

But when I use vModel: "form_data[key]" or vModel: "form_data.key", neither work. It seems the correct way to write in general is: vModel: "form_data.a"?

How to solve this in the for-loop?


Edit: The actual case is an IView Form. Example:

<Form :model="formValidate">
    <FormItem label="E-mail" prop="mail">
        <Input v-model="formValidate.mail" placeholder="Enter your e-mail"></Input>
    </FormItem>
</Form>

My form_data in this example is the formValidate. I use the for-loop generate the form_data, but I can not use "form_data.a". How to bind the v-model (of the custom component Input) now?

4
  • 2
    so what is your desire output? Commented Apr 3, 2018 at 13:07
  • @PankajBisht not output. in render function its standard code just like: vModel: ’form_data.a’but i use the for loop generate the form_data. i can^t know the key. Commented Apr 3, 2018 at 13:17
  • 2
    Why do you assign undefined instead of label_key_map[key]? Commented Apr 3, 2018 at 13:20
  • the form_data bind to the form. the form_item bind the form_data.x. the initial data should be undefined or ‘’ Commented Apr 3, 2018 at 13:23

2 Answers 2

3

Don't use arrow functions in the render declaration. About the usage of render functions, to generate attributes, use attrs, not props. Also, quoting the Render Functions & JSX docs:

There is no direct v-model counterpart in render functions - you will have to implement the logic yourself.

Below demos of how that could be achieved.

Declaring, in render function, v-model for DOM native elements (e.g. <input>)

new Vue({
  el: '#app',
  data: {
      form_data: { a: "1", b: "2", c: "3", d: "4" }
  },
  render(h) { // dont use arrow function
    var self = this
    var form_items = [];
    for (let key in self.form_data) {
        var form_item = h('div', {},
            [
               key + ':',
               h('input', {
                  attrs: {type: "text"},
                  // simulate "v-model"
                  domProps: {value: self.form_data[key]}, on: {input: function (event) { self.form_data[key] = event.target.value }}
               })
            ]
        );
        form_items.push(form_item);
    }
    var form = h('form', {}, form_items);

    return h('div', {}, [
        form,
        h('pre', JSON.stringify(this.form_data)) // added for visual debug
    ]);
  }
});
<script src="https://unpkg.com/vue"></script>

<div id="app"></div>

Declaring, in render function, v-model for DOM custom components (e.g. <Inputx>)

In this example, the declarations simulate the usage of IView's <Form>, <FormItem> and <Input>, which are vue custom components. In the code below I added an x to the component's names so the reader at a glance don't confuse them with the native <form> or <input> (what actually happened to me at first).

// declaring some custom components to simulate https://www.iviewui.com/components/form
Vue.component('Formx', {template: '<div>Form\'s model: {{ model }} <hr><slot></slot></div>', props:['model']})
Vue.component('FormItemx', {template: '<div><slot></slot></div>'})
Vue.component('Inputx', {template: '<div><input :value="value" @input="$emit(\'input\', $event.target.value)"></div>', props:['value']})

new Vue({
    el: '#app',
    data: {
        form_data: { a: "1", b: "2", c: "3", d: "4" }
    },
    render(h) { // don't use arrow function here
        var self = this
        var form_items = [];
        for (let key in self.form_data) {
            var form_item = h('FormItemx', {
                attrs: {prop: key}},
                [h('Inputx', {
                    attrs: {type: "text"},
                    // custom component "v-model"
                    model:{
                      value: self.form_data[key],
                      callback: (v) => self.$set(self.form_data, key, v),
                      expression:"form_data["+key+"]"
                    }
                })]
            );
            form_items.push(form_item);
        }
        return h('Formx', {attrs:{"model":this.form_data}}, form_items);
    }
});
<script src="https://unpkg.com/vue"></script>

<div id="app"></div>

Sign up to request clarification or add additional context in comments.

6 Comments

i follow the iview form. the form_item has those props.
It has attributes, not props. In <FormItem prop="user"> we have an attribute called prop. But, anyway, the code above was an example. If you find out it doesn't work due to attrs, then change to props.
thanks for your attention, I did not work out, and I am also looking for a solution in my way.
That's the Form is a iView component that bind the :model="form_data", and its <FormItem>'s <Input> bind the form_data. property, which is the API of iView <Form> and <Input>. I can not bind this in the generated form_data.
Oh, I think I understand what you needed, now. Can you check the updated answer? I think it should work. (If you need to see exactly what I changed, check the revision page of the answer.)
|
1
h('custom-component',{
    model:{
        value: self.form_data[key],
        callback: (v) => self.$set(self.form_data, key, v),
        expression:"form_data["+key+"]"
    }
});

This way can make v-model working, but not the recommended way of use.

My suggestion is still using value dom attribute and input event for custom component like below:

h('custom-component',{
    attrs:{
        value: this.myValue
    },
    on:{
        input: val => this.myValue = val
    }
})

For native element:

h('input',{
    attrs:{
        type:'text'
    },
    domProps:{
        value: this.myValue
    },
    on:{
        input: val => this.myValue = val
    }
})

More detail in code: github.com/TerryZ/vue-plugins

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.