really need your help. I'm trying to write a function that would generate HTML markup from javascript object.
My thoughts is I send an object and a root element as parameters and recursively append elements.
Here is the code.
const struct = [
{
tag: 'div',
classes: ['container'],
innerHtml: [
{
tag: 'input',
classes: ['input'],
attributes: [
['type', 'text'],
['placeholder', 'Some input']
]
},
{
tag: 'div',
classes: ['btn-block'],
innerHtml: [
{
tag: 'div',
classes: ['btn', 'btn-long'],
innerText: 'Long Button'
},
{
tag: 'div',
classes: ['btn', 'btn-big', 'btn-img'],
innerHtml: [
{
tag: 'img',
attributes: [
['src', 'https://www.w3schools.com/images/w3certified_logo_250.png']
],
}
],
}
]
},
{
tag: 'div',
classes: ['red']
}
]
}
];
const root = document.body;
function create(obj, root) {
obj.forEach(o => {
const element = document.createElement(o.tag);
if (o.classes) {
const classes = o.classes;
element.classList.add(...classes);
}
if (o.attributes) {
o.attributes.forEach(a => {
element.setAttribute(a[0], a[1]);
})
}
if (o.hasOwnProperty('innerHtml')) {
element.append(create(o.innerHtml, element));
}
if (o.innerText) {
element.innerText = o.innerText
}
root.append(element);
});
}
create(struct, root);
And there is a result ;
As you can see the function add text 'Undefined' to every element.
Could you help me to fix it?
UPD: Solved by answers from @CertainPerformance and @Nina Scholz
You need only
create(o.innerHtml, element);
without wrapping element.append(/* ... */);
because your function does not return somthing.
function create(obj, root) { obj.forEach(o => { const element = document.createElement(o.tag); if (o.classes) { const classes = o.classes; element.classList.add(...classes); } if (o.attributes) { o.attributes.forEach(a => { element.setAttribute(a[0], a[1]); }) } if (o.hasOwnProperty('innerHtml')) { create(o.innerHtml, element); //element.append(); } if (o.innerText) { element.innerText = o.innerText } root.append(element); }); } const struct = [{ tag: 'div', classes: ['container'], innerHtml: [{ tag: 'input', classes: ['input'], attributes: [ ['type', 'text'], ['placeholder', 'Some input'] ] }, { tag: 'div', classes: ['btn-block'], innerHtml: [{ tag: 'div', classes: ['btn', 'btn-long'], innerText: 'Long Button' }, { tag: 'div', classes: ['btn', 'btn-big', 'btn-img'], innerHtml: [{ tag: 'img', attributes: [ ['src', 'https://www.w3schools.com/images/w3certified_logo_250.png'] ], }], } ] }, { tag: 'div', classes: ['red'] } ] }]; const root = document.body; create(struct, root);
The problem is
element.append(create(o.innerHtml, element));
But create
doesn't return anything, so undefined
is appended to the end of every element. Change to just
create(o.innerHtml, element)
instead:
const struct = [{ tag: 'div', classes: ['container'], innerHtml: [{ tag: 'input', classes: ['input'], attributes: [ ['type', 'text'], ['placeholder', 'Some input'] ] }, { tag: 'div', classes: ['btn-block'], innerHtml: [{ tag: 'div', classes: ['btn', 'btn-long'], innerText: 'Long Button' }, { tag: 'div', classes: ['btn', 'btn-big', 'btn-img'], innerHtml: [{ tag: 'img', attributes: [ ['src', 'https://www.w3schools.com/images/w3certified_logo_250.png'] ], }] } ] }, { tag: 'div', classes: ['red'] } ] }]; const root = document.body; function create(obj, root) { obj.forEach(o => { const element = document.createElement(o.tag); if (o.classes) { const classes = o.classes; element.classList.add(...classes); } if (o.attributes) { o.attributes.forEach(a => { element.setAttribute(a[0], a[1]); }) } if (o.hasOwnProperty('innerHtml')) { create(o.innerHtml, element) } if (o.innerText) { element.innerText = o.innerText } if (element !== undefined) { root.append(element); } }); } create(struct, root);
.container { padding: 5px; border: 1px solid black; display: flex; justify-content: space-around; align-items: center; } .input { height: 20px; width: 200px; } .btn-block { display: flex; justify-content: space-around; align-items: center; } .btn { border: 1px solid black; border-radius: 5px; padding: 5px 15px; text-align: center; } .btn:hover { cursor: pointer; } .btn-long { width: 300px; margin-right: 10px; } .red { background: red; height: 100px; width: 100px; }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.