Javascript递归对象迭代生成表单元素名称

时间:2018-03-16 18:32:38

标签: javascript forms loops recursion logic

我有一个AJAX响应,其中包含一个对象,用于存储我的所有表单元素结构及其各自的错误消息(如果有的话)。 该对象结构如下构建:

var obj = {
    'entity1': { //Entity
        'attribute1': { //Field
            'isEmpty': "This value is required" //rule with error message
        },
        'attribute2': { //Field
            'isEmpty': "This value is required" //rule with error message
        }
    },
    'entity2': { //Entity
        'attribute1': { //Field
            'isEmpty': "This value is required" //rule with error message
        },
        'attribute2': { //Field
            'isEmpty': "This value is required" //rule with error message
        }
    }
};

所有这些字段都存储在由主实体包围的表格中,如下所示:

<input name="mainentity[entity1][attribute1]" />
<input name="mainentity[entity1][attribute2]" />
<input name="mainentity[entity2][attribute1]" />
<input name="mainentity[entity2][attribute2]" />
...

基本上,我需要的是迭代这个对象组装输入的名称,以便能够使用jQuery找到它们,所以我可以将它们各自的错误消息添加到DOM中。

我尝试在javascript中创建此功能:

var prefix = 'mainentity', inputs = {};
function iterate(obj, partialName, isChild) {
    for (var property in obj) {
        if (obj.hasOwnProperty(property)) {
            switch (typeof obj[property]) {
                case 'string':
                    if (!inputs.hasOwnProperty(partialName)) {
                        inputs[partialName] = [];
                    }
                    inputs[partialName].push(obj[property]);
                    break;
                default:
                    if (isChild) {
                        partialName += '[' + property + ']';
                    } else {
                        partialName = prefix + '[' + property + ']';
                    }
                    iterate(obj[property], partialName, true);
                    break;
            }
        }
    }
};
iterate(obj);
console.log(inputs);

我基于属性的类型。如果是string,那么这是一条消息。否则,它是递归中需要考虑的字段。我试图仅使用标记isChild知道我何时会破坏partialName并重新开始作为新属性。

问题是最终结果变成了这样:

{
    'mainEntity[entity1][attribute1]': ["This value is required"],
    'mainEntity[entity1][attribute1][attribute2]': ["This value is required"], //wrong result, attribute1 shouldn't be here
    'mainEntity[entity2][attribute1]': ["This value is required"],
    'mainEntity[entity2][attribute1][attribute2]': ["This value is required"], //wrong result, attribute1 shouldn't be here
}

我希望如此:

{
    'mainEntity[entity1][attribute1]': ["This value is required"],
    'mainEntity[entity1][attribute2]': ["This value is required"], //No attribute 1 here
    'mainEntity[entity2][attribute1]': ["This value is required"],
    'mainEntity[entity2][attribute2]': ["This value is required"], //No attribute 1 here
}

我理解这个问题。 isChild标志仅适用于更高级别,并且考虑到在我的逻辑中,从递归开始的所有内容都是小孩,partialName无法正常工作。

如何让这个功能正常运作?我的意思是,我怎么知道将部分名称分解为新输入而不是连接到错误的先前字段的正确时间,并使其适用于具有N个嵌套响应对象的任何情况?

1 个答案:

答案 0 :(得分:1)

此替代方法以递归方式循环,并连接对象中每个新找到的键。

&#13;
&#13;
var obj = {  'entity1': {    'attribute1': {       'isEmpty': "This value is required1"     },    'attribute2': {      'isEmpty': "This value is required2"     }  },  'entity2': {  'attribute1': {       'isEmpty': "This value is required3"  },    'attribute2': {     'isEmpty': "This value is required4"   }  }};

function loop(o, currentPath, result) {
  Object.keys(o).forEach(function(k) {
    if (typeof o[k] === 'string') result[`${currentPath}`] = [o[k]];
    else loop(o[k], `${currentPath}[${k}]`, result);    
  });
}

var result = {};
loop(obj, 'mainEntity', result);

console.log(result);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;