简体   繁体   中英

Expand object literal as html5 data- attributes

It is possible to expands an object literal as html5 data- attributes?

Having the following object:

const requirements = {
    'data-description': 'some text...',
    'data-pointer': true,
    'data-speaker': true
}

I would like to expand it in a anchor tag in order to get something like this:

<a href="#" class="show-modal" data-description="some-text" data-pointer="true" data-speaker="true">Show modal</a>

I tried to use the spread syntax in this way <a href="#" class="show-modal" `${...requirements}`>Show modal</a> But nothing get printed

I am now depending on this function that builds an anchor and passes the data dynamically.

function buildAnchor(requirements) {
    const anchor = document.createElement('a');

    anchor.setAttribute('class', 'show-modal');
    anchor.setAttribute('href', '#');
    anchor.textContent = 'More info';

    Object.keys(requirements).forEach(data => {
        anchor.setAttribute(data, requirements[data]);
    });

    return anchor.outerHTML;
}

This function do the job, but i would like to know if it's possible to use spread syntax

Thanks in advance

How about straightforwardly using an HTMLElement 's dataset property and then assigning a simplified configuration object to it via Object.assign ... like ...

 var requirements = { 'description': 'some text...', 'pointer': true, 'speaker': true }; var elmLink = document.createElement('a'); elmLink.href = ''; Object.assign(elmLink.dataset, requirements); console.log('elmLink : ', elmLink); 
 .as-console-wrapper { max-height: 100%!important; top: 0; } 

You can define the data-* attribute as a single JSON string, then use JSON.parse() to create a JavaScript object representation of the .dataset property.

Note the single quote surrounding attribute value within template literal that surrounds valid JSON at HTML string.

 const requirements = { 'description': 'some text...', 'pointer': true, 'speaker': true } const a = `<a data-requirements='${JSON.stringify(requirements)}'>click</a>`; document.body.insertAdjacentHTML("beforeend", a); let data = JSON.parse(document.querySelector("a").dataset.requirements); console.log(data, data.description, data.pointer, data.speaker); 

The spread syntax won't do what you want. That's really for including key/value pairs from one object into another, or for destructuring assignment.

You can use Object.entries() with .map() and .join() inside a template literal.

 const requirements = { 'data-description': 'some text...', 'data-pointer': true, 'data-speaker': true }; const s = `<a href="#" class="show-modal" ${Object.entries(requirements).map(([k, v]) => k + "='" + v + "'").join(" ")}>Show modal</a>`; console.log(s); 


I think it would be cleaner to move the attribute creation into its own function.

 const requirements = { 'data-description': 'some text...', 'data-pointer': true, 'data-speaker': true }; const s = `<a href="#" class="show-modal" ${oToA(requirements)}>Show modal</a>`; console.log(s); function oToA(obj) { return Object.entries(obj) .map(([k, v]) => k + "='" + v + "'") .join(" ") } 

You could enhance the function by replacing embedded quotes with HTML entities.

From MDN:

Spread syntax allows an iterable such as an array expression to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Since you are trying to build a function that takes in the requirements as arguments (not key/value pairs), an array structure would make better sense than an object structure.

 const requirements = [ {'data-description': 'some text...'}, {'data-pointer': true}, {'data-speaker': true} ]; (function populate(){ var anchor = document.createElement("a"); // Convert the arguments object to an array and enumerate it // so that each object key can become an attribute and the // corresponding value can become the value: Array.prototype.slice.call(arguments).forEach(function(arg){ for(var prop in arg){ anchor.setAttribute(prop, arg[prop]); } }); console.log(anchor); })(...requirements); 

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.

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