简体   繁体   English

VueJS - 从递归树中获取输入值

[英]VueJS - get input values from a recursive tree

I have the need to create a dynamic form, which builds up in a tree kind of way.我需要创建一个动态表单,它以树的方式构建。 The form can change at any time by the user (who creates/designs the form) and so the inputs I have change dynamically too.用户(创建/设计表单的人)可以随时更改表单,因此我的输入也会动态变化。

Example:例子:

root
--groeisnelheid
----niveau
------beginner (input radio)
------recreatief (input radio)
------competitie (input radio)
------tour (input radio)
----input text
----begeleiding
------another input
------and another
--another category
----speed
------input
------input

As you can see, not the easiest form... The user (admin user in this case) has the ability to edit or create new forms.如您所见,这不是最简单的形式...用户(在本例中为管理员用户)具有编辑或创建新 forms 的能力。

I probably have underestimated the job, since I am trying to create the input side of it, and am already struggling.我可能低估了这份工作,因为我正在尝试创建它的输入端,并且已经在苦苦挣扎。

What I have done so far:到目前为止我做了什么:

TreeComponent.vue树组件.vue

<template>
    <div class="tree">
        <ul class="tree-list">
            <tree-node :node="treeData"></tree-node>
        </ul>
    </div>
</template>

<script>
export default {
    props: {
        treeData: [Object, Array]
    },

    data() {
        return {
            treeValues: []
        };
    },

    methods: {
        sendForm: function() {}
    }
};
</script>

TreeNodeComponent.vue树节点组件.vue

<template>
    <li v-if="node.children && node.children.length" class="node">
        <span class="label">{{ node.name }}</span>

        <ul>
            <node v-for="child in node.children" :node="child" :key="child.id"></node>
        </ul>
    </li>
    <div v-else class="form-check form-check-inline">
        <input
            type="radio"
            class="form-check-input"
            :name="'parent-' + node.parent_id"
            :id="node.id"
        />
        <label for class="form-check-label">{{ node.name }}</label>
    </div>
</template>

<script>
export default {
    name: "node",
    props: {
        node: [Object, Array]
    }
};
</script>

This results in all the inputs showing up as I want.这导致所有输入都按我的意愿显示。 But now the real question is;但现在真正的问题是; how do I get the value of these inputs in my root component (TreeComponent.vue), so I can send this to the server.如何在我的根组件(TreeComponent.vue)中获取这些输入的值,以便将其发送到服务器。 Either on change or when the user proceeds in the form.在更改时或当用户在表单中继续时。

I am used to working with v-model on this, but I have no clue on how to use this on recursive components, since the documentation only covers setting the data of the direct parent.我习惯于在这方面使用v-model ,但我不知道如何在递归组件上使用它,因为文档仅涵盖设置直接父级的数据。

Any help would be much appreciated.任何帮助将非常感激。

One way of doing this is to pass a prop down from TreeComponent to each node.一种方法是从TreeComponent向下传递一个 prop 到每个节点。

<template>
  <div class="tree">
    <ul class="tree-list">
        <tree-node :node="treeData" :form="formRepo"></tree-node>
    </ul>
  </div>
</template>

Then each node passes the prop down to its children.然后每个节点将 prop 向下传递给它的子节点。

 <node v-for="child in node.children" :node="child" :key="child.id" :form="form"></node>

This way each node will have a direct reference to the TreeComponent .这样,每个节点都将直接引用TreeComponent

In each node you can watch the model and update the form prop.在每个节点中,您可以查看model 并更新form属性。 You need to use your child.id so you know which field is which.您需要使用child.id以便知道哪个字段是哪个字段。

Your formRepo can be a fully fledged object, but a hash could work just as well.您的formRepo可以是成熟的 object,但 hash 也可以正常工作。

data() {
    return {
        treeValues: [],
        formRepo: {
        }
    };
}

Note: if you want formRepo to be reactive you'll need to use Vue.set to add new keys to it.注意:如果您希望formRepo具有响应性,您需要使用Vue.set向其中添加新键。

Thank you for your answer.谢谢您的回答。

I managed to solve it by posting the data to the server on every change, since this was a handy feature.我设法通过在每次更改时将数据发布到服务器来解决它,因为这是一个方便的功能。

The way I did so was:我这样做的方式是:

Call function from the input (same call for text inputs)从输入调用 function(对文本输入的调用相同)

<input
    type="radio"
    class="form-check-input"
    :name="'parent-' + node.parent_id"
    :id="node.id"
    @input="change($event, node.id, node.parent_id)"
/>

Have some data variables to fill (Route is required for the axios request)有一些数据变量要填写(axios 请求需要路由)

data() {
    return {
        input: {
            id: null,
            parentId: null,
            radio: false,
            value: null
        },
        route: null
    };
},

And then some magic.然后是一些魔法。 The change method.改变方法。 (Left the axios bit out.) (留下 axios 位。)

methods: {
    change: function(event, id, parentId) {
        this.input.parentId = parentId;
        this.input.id = id;

        if (event.target.value === "on" || event.target.value === "off") {
            this.input.radio = true;
            this.input.value = event.target.value === "on" ? true : false;
        } else {
            this.input.value = event.target.value;
        }

        if (this.input.value) {
            axios.put().then().catch()
        }
    }
}

I know there is some room of improvement in the validation bit.我知道验证位有一些改进的余地。 If a user enters 'on' in a text field, this will probably fail.如果用户在文本字段中输入“on”,这可能会失败。 So there is work to be done, but the basic filling of a form is working.所以有工作要做,但表格的基本填写是有效的。

As to if this is the best way, I have no clue, since I'm new to Vue.至于这是否是最好的方法,我不知道,因为我是 Vue 的新手。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM