Structuring and Binding (ajax response)

◇◆丶佛笑我妖孽 提交于 2019-12-08 11:39:38

问题


One of the common patterns I've come across in my many years of coding is the structuring/binding of the data coming from the server response (XMLHttpRequest). This problem of creating elements and appending them in a particular order as well as binding (attributes,events,content) is what I'm am trying to achieve here.


For example purposes and simplicity I am trying to create a tr --- td nested structure as well as bind the attributes from the var instructs object (table-row,table-data).

JSON Response (dummy data)

var response =[{"employeeNumber":"1002","lastName":"Murphy","firstName":"Diane","extension":"x5800","email":"dmurphy@classicmodelcars.com","officeCode":"1","reportsTo":null,"jobTitle":"President"},{"employeeNumber":"1056","lastName":"Patterson","firstName":"Mary","extension":"x4611","email":"mpatterso@classicmodelcars.com","officeCode":"1","reportsTo":"1002","jobTitle":"VP Sales"},{"employeeNumber":"1076","lastName":"Firrelli","firstName":"Jeff","extension":"x9273","email":"jfirrelli@classicmodelcars.com","officeCode":"1","reportsTo":"1002","jobTitle":"VP Marketing"},{"employeeNumber":"1088","lastName":"Patterson","firstName":"William","extension":"x4871","email":"wpatterson@classicmodelcars.com","officeCode":"6","reportsTo":"1056","jobTitle":"Sales Manager (APAC)"},{"employeeNumber":"1102","lastName":"Bondur","firstName":"Gerard","extension":"x5408","email":"gbondur@classicmodelcars.com","officeCode":"4","reportsTo":"1056","jobTitle":"Sale Manager (EMEA)"},{"employeeNumber":"1143","lastName":"Bow","firstName":"Anthony","extension":"x5428","email":"abow@classicmodelcars.com","officeCode":"1","reportsTo":"1056","jobTitle":"Sales Manager (NA)"},{"employeeNumber":"1165","lastName":"Jennings","firstName":"Leslie","extension":"x3291","email":"ljennings@classicmodelcars.com","officeCode":"1","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1166","lastName":"Thompson","firstName":"Leslie","extension":"x4065","email":"lthompson@classicmodelcars.com","officeCode":"1","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1188","lastName":"Firrelli","firstName":"Julie","extension":"x2173","email":"jfirrelli@classicmodelcars.com","officeCode":"2","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1216","lastName":"Patterson","firstName":"Steve","extension":"x4334","email":"spatterson@classicmodelcars.com","officeCode":"2","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1286","lastName":"Tseng","firstName":"Foon Yue","extension":"x2248","email":"ftseng@classicmodelcars.com","officeCode":"3","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1323","lastName":"Vanauf","firstName":"George","extension":"x4102","email":"gvanauf@classicmodelcars.com","officeCode":"3","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1337","lastName":"Bondur","firstName":"Loui","extension":"x6493","email":"lbondur@classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1370","lastName":"Hernandez","firstName":"Gerard","extension":"x2028","email":"ghernande@classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1401","lastName":"Castillo","firstName":"Pamela","extension":"x2759","email":"pcastillo@classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1501","lastName":"Bott","firstName":"Larry","extension":"x2311","email":"lbott@classicmodelcars.com","officeCode":"7","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1504","lastName":"Jones","firstName":"Barry","extension":"x102","email":"bjones@classicmodelcars.com","officeCode":"7","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1611","lastName":"Fixter","firstName":"Andy","extension":"x101","email":"afixter@classicmodelcars.com","officeCode":"6","reportsTo":"1088","jobTitle":"Sales Rep"},{"employeeNumber":"1612","lastName":"Marsh","firstName":"Peter","extension":"x102","email":"pmarsh@classicmodelcars.com","officeCode":"6","reportsTo":"1088","jobTitle":"Sales Rep"},{"employeeNumber":"1619","lastName":"King","firstName":"Tom","extension":"x103","email":"tking@classicmodelcars.com","officeCode":"6","reportsTo":"1088","jobTitle":"Sales Rep"},{"employeeNumber":"1621","lastName":"Nishi","firstName":"Mami","extension":"x101","email":"mnishi@classicmodelcars.com","officeCode":"5","reportsTo":"1056","jobTitle":"Sales Rep"},{"employeeNumber":"1625","lastName":"Kato","firstName":"Yoshimi","extension":"x102","email":"ykato@classicmodelcars.com","officeCode":"5","reportsTo":"1621","jobTitle":"Sales Rep"},{"employeeNumber":"1702","lastName":"Gerard","firstName":"Martin","extension":"x2312","email":"mgerard@classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"}];

Binding (instructions)

var instructs={
    tag:"tr",
    attributes:{class:"table-row"},
    props:{
        email:{
            tag:"td",
            content: null,
            attributes:{class:"table-data",id:"table-data-id"}
        },
        employeeNumber:{
            tag:"td",
            attributes:{class:"table-data"},
            content: null,
            props:{
                x:{
                    tag: "input",
                    attributes:{class:"table-input"},
                    content: "test"
                }
            }
        },
        extension:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        firstName:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        jobTitle:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        lastName:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        officeCode:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        },
        reportsTo:{
            tag:"td",
            content: null,
            attributes:{class:"table-data"}
        }
    }
};

My Function (assemble)

function assemble(r,s,n){
    var n = n || new DocumentFragment();    
    if(typeof r !== 'string'){ //HAS CHILDREN
        r.forEach((o)=>{ 
            for(y in s){
                switch(y){
                    case "tag":
                        var tag = document.createElement(s[y]);
                        n.appendChild(tag);
                        break;
                    case "attributes":
                        for(a in s[y]) tag.setAttribute(a,s[y][a]);
                        break;
                    case "content":
                        if(s.content === null){
                            //append current property value
                        }
                        else{
                            tag.innerHTML = s.content;
                        }
                        break;
                    case "props":
                        for(k in o) assemble(k,s[y][k],tag); //EXECUTE PER CHILDREN
                        break;
                }
            }
        });
    }
    else{
        for(x in s){
            switch(x){
                case "tag":
                    var tag = document.createElement(s[x]);
                    n.appendChild(tag);
                    break;
                case "content":
                    if(s.content === null){
                        //append current property value
                    }
                    else{
                        tag.innerHTML = s.content;
                    }
                    break;
                case "attributes":
                    for(a in s[x]) tag.setAttribute(a,s[x][a]);
                    break;
                case "props":
                    for(c in s[x]) assemble(r,s[x][c],tag);
                    break;
            }
        }   
        return n;
    }
    return n;
}               

document.addEventListener('DOMContentLoaded',()=>{
     var data = assemble(response,instructs);           
     console.log(data);
});

The end result I'm looking for is an array/fragment of nested tr>td both with a class attribute and the values append to the innerHTML.

<tr class ="table-row">
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
    <td class="table-data">how do I bind the response values?</td>
</tr>

QUESTION:

How can I bind the property values from the response to the innerHTML of the td's?


回答1:


Give a try to the following one. Sorry, I started refactoring Yours and in the end I had rewritten it. Take care that the content is always taken as innerHTML, it would not be a bad idea at all to differentiate text(append createTextNode func outcome) and html(innerHTML prop). In your data instructs.props.employeeNumber.props.x.content should be moved into instructs.props.employeeNumber.props.x.attributes.value seen how works the input[text] tag. Btw I see there are a lot of stuff that could be discussed here. Hope it helps!

function assemble (data, instr) {
    var n = document.createDocumentFragment(), i;
    function create(d) {
        var objData = d;
        return (function _(_instr, _key, _n) {
            var innerHTML = !!_key && _key in objData ? objData[_key] : null,
                tag = null, i;
            if ('tag' in _instr) {
                tag = document.createElement(_instr.tag);
                tag.innerHTML = 'content' in _instr && !!_instr.content ? _instr.content : innerHTML;

                if ('attributes' in _instr) {
                    for (i in _instr.attributes) tag.setAttribute(i, _instr.attributes[i]);
                }
                //recur finally
                if ('props' in _instr) {
                    for (i in _instr.props) _(_instr.props[i], i, tag);
                }
                !!_n && _n.appendChild(tag);
            }
            return tag;
        })(instr, null);

    }
    return (function (){
        for (i in data) {
            n.appendChild(create(data[i]));
        }
        return n;
    })();
}



回答2:


Though my answer does not address the code context from the question, but for structuring and binding json response i usually use regex templating. I find it simple in declaration and concise. ex,

html:

<table>
  <tbody id="employee">
  </tbody>
</table>

js:

var template = function(tpl, data) {
  return tpl.replace(/\$\{([^\}]+)?\}/g, function($1, $2) {
    return data[$2];
  });
};

var rowTemplate = '<tr class ="table-row">\
                     <td class="table-data">${email}</td>\
                     <td class="table-data"><input type="text" value=' ${employeeNumber}' /></td>\
                     <td class="table-data">${firstName}</td>\
                     <td class="table-data">${lastName}</td>\
                     <td class="table-data">${email}</td>\
                     <td class="table-data">${jobTitle}</td>\
                     <td class="table-data">${extension}</td>\
                   </tr>';

var response = [{"employeeNumber":"1002","lastName":"Murphy","firstName":"Diane","extension":"x5800","email":"dmurphy@classicmodelcars.com","officeCode":"1","reportsTo":null,"jobTitle":"President"}, ....]

var b = document.getElementById('employee');

for (var i = 0; i < response.length; i++) {
  var tr = document.createElement('x');
  b.appendChild(tr);
  tr.outerHTML = template(rowTemplate, response[i]);
}

fiddle

hope this helps.



来源:https://stackoverflow.com/questions/36581180/structuring-and-binding-ajax-response

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!