1. Dynamically query rules

The following figure shows the dynamic query rules. It is a complex component that can organize query statements according to user’s customization, and can roughly realize the WHERE condition of SQL query. The following is a software excerpt from mongodb.

2. Component construction ideas

The way the regular components are organized, you can think of it as a tree, with a trunk and leaves, so it doesn’t look hard.

2.1 Component Properties

  • Data: is the content of the tree structure, which we define as:
{
condition: 'AND'.rules: [],}Copy the code
  • FieldList: Array of field lists, a collection of fields to choose from;
  • OperatorList: Array of operation lists, a collection of optional operations, defined as follows:
{
     label: 'contains'.value: '⊂',},Copy the code

2.2 components HTML

This is built with ElementUI, so you can easily combine various UI controls to build the desired interface. Of course, since this component is considered a tree, it is also a recursive component and therefore involves calling itself.

<template>
    <div class="rules-group-container">
        <div class="rules-group-header">
            <el-radio-group v-model="data.condition" size="mini">
                <el-radio-button label="AND"></el-radio-button>
                <el-radio-button label="OR"></el-radio-button>
            </el-radio-group>
            <div>
                <el-button size="mini" @click="addRule(data)">Add rules</el-button>
                <el-button size="mini" @click="addGroup(data)">Add a group</el-button>
                <el-button v-if="parent" size="mini" @click="delGroup(data, parent)">delete</el-button>
            </div>
        </div>
        <div class="rules-group-body">
            <div class="rules-list">
                <template v-for="(rule, index) in data.rules">
                    <div :key="index" v-if=! "" rule.condition" class="rule-container">                        
                        <! - field -- - >
                        <wt-dropdown
                            class="rule-item"
                            v-model="rule.FilterField"
                            :data="getFieldList(rule.FilterTable)"
                            @change="handleFieldChange(rule)"
                        ></wt-dropdown>
                        <! -- operator -->
                        <wt-dropdown
                            class="rule-item"
                            v-model="rule.Operator"
                            :disabled="inputStatus && rule.FilterField === 'CommunityId'"
                            :data="getRule(rule.FilterTable, rule.FilterField)"
                        ></wt-dropdown>
                        <! - value - >
                        <wt-multi-dropdown
                            class="rule-item-long"
                            v-if="rule.type === 'Dropdown'"
                            :disabled="inputStatus && rule.FilterField === 'CommunityId'"
                            v-model="rule.FilterValue"
                            :data="getData(rule.FilterTable, rule.FilterField)"
                        ></wt-multi-dropdown>
                        <wt-number
                            class="rule-item-long"
                            :disabled="inputStatus && rule.FilterField === 'CommunityId'"
                            v-else-if="['DateTime', 'Number', 'Decimal'].includes(rule.type)"
                            v-model="rule.FilterValue"
                        ></wt-number>
                        <wt-text class="rule-item-long" v-else v-model="rule.FilterValue" :disabled="inputStatus && rule.FilterField === 'CommunityId'"></wt-text>
                        <el-button size="mini" @click="delRule(index)">delete</el-button>
                    </div>
                    <CreateRule
                        :key="index"
                        v-else
                        :data="rule"
                        :parent="data"
                        :fieldList="fieldList"
                        :operatorList="operatorList"
                    ></CreateRule>
                </template>
            </div>
        </div>
    </div>
</template>
Copy the code

2.3 Define different conditions for fields of different data types

const rules = {
    string: [{value: '= ='.label: 'equal to'}, {value: '< >'.label: The prime is not equal to the prime.}, {value: '⊂'.label: 'contains'}, {value: '⊄'.label: 'Not included'}, {value: 'in'.label: 'One of'}, {value: 'ni'.label: 'Not one of them'}, {value: 'mc'.label: 'More contains'],},number: [{value: '= ='.label: 'equal to'}, {value: '< >'.label: The prime is not equal to the prime.}, {value: 'or'.label: The prime is greater than or equal to the prime.}, {value: 'or less'.label: 'Less than or equal to'.],},dict: [{value: 'in'.label: 'One of'}, {value: 'ni'.label: 'Not one of them'],},date: [{value: 'sdiff'.label: 'A few days ago'}, {value: 'ediff'.label: 'In a few days',},],}Copy the code

2.4 Define method operation groups \ rules

The main operations involve adding \ deleting groups and rules.

getRule(table, field) {
            let data = (rules && rules.string) || []
            let theField = this.getCurrentField(table, field)
            if (theField && theField.ControlType) {
                if (['Dropdown'].includes(theField.ControlType)) {
                    return rules.dict
                } else if (['DateTime'].includes(theField.ControlType)) {
                    return rules.date
                } else if (['Number'.'Decimal'].includes(theField.ControlType)) {
                    return rules.number
                } else {
                    return rules.string
                }
            }
            return data
        },
        // Add the rule
        addRule(data) {
            let rule = {
                type: 'Text'.FilterTable: this.firstTable,
                FilterField: this.firstField,
                Operator: '= ='.FilterValue: ' ',
            }
            data.rules.push(rule)
        },
        // Delete the rule
        delRule(index) {
            this.data.rules.splice(index, 1)},// Add a group
        addGroup(data) {
            let group = {
                condition: 'OR'.rules: [{type: 'Text'.FilterTable: this.firstTable,
                        FilterField: ' '.Operator: ' '.FilterValue: ' ',
                    },
                ],
            }
            data.rules.push(group)
        },
        // Delete the group
        delGroup(data, parent) {
            let index = parent.rules.findIndex((item) = > item === data)
            parent.rules.splice(index, 1)},Copy the code

2.5 Defining component Names

This component is named CreateRule, and defining the code is simple.

export default {
    name: 'CreateRule'.props: {
        parent: {
            type: Object,},data: {
            type: Object,},fieldList: {
            type: Array.default() {
                return[]}},operatorList: {
            type: Array.default() {
                return[]},},},}Copy the code

3. Use components

Components used in VUE are simply referenced and added to the list of components.

import CreateRule from './CreateRule'
export default {
    name: 'NewRuleForm'.components: {
        CreateRule,
    },
}
Copy the code

Adding a reference to a template

<template>
    <div class="new-rule-form">
        <CreateRule
            v-if=! "" loading"
            :data="data"
            :fieldList="FilterTable"
            :operatorList="operatorList"
        ></CreateRule>
        <div v-if=! "" loading" class="discription-wrap" v-html="discription"></div>
    </div>
</template>
Copy the code

4. Effect display

This is the actual effect of the intercept.It works well as a search condition or filter condition in the interface and can be very flexible.

5. Summary

In the development of VUE applications, we can refer to some interfaces of Windows software, which can occasionally give us great inspiration and inspiration. Of course, also hope this article can help small friends.