0

The inline style attributes has values such as style = "color: green; background: red;". If I want to dynamically change only the background I change with the Javascript attribute style, I do it with:

element.style.background = "blue"

How to create a "custom" attribute so that the values within an attribute can change dynamically?

For example:

myAttributes = "car: mercedes; truck: volvo;"

so that I change only car values dynamically as style changes, as an

element.myAttributes.car = "ferrari"

or with

setAttributes ("myAttributes", car = "ferrari" )

Is there a possibility to do this, or some similar alternative, some idea?

var get_att = document.getElementById("demo").getAttribute("vehicles");

// how to get vehicles attributes and convert to object?

const vehicles = {car:"mercedes", truck:"volvo"}; 
// const vehicles = get_att; 
// how to add the get_att variable here?

vehicles.car = "ferrari";

const setVehicles = (Object.entries(vehicles).map(([k, v]) => `${k}: ${v}`).join("; "));
console.log(setVehicles);

document.getElementById("demo").setAttribute("vehicles", setVehicles);
<div id="demo" vehicles="car: mercedes; truck: volvo"></div>
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
maja
  • 177
  • 1
  • 13
  • Does this answer your question? [Custom attributes - Yea or nay?](https://stackoverflow.com/questions/992115/custom-attributes-yea-or-nay) – Archit Gargi Mar 07 '22 at 13:03
  • `element.setAttribute('attrName', 'attrVal')` ... (and maybe, use `data-...` attribute name ...) – Vovan_Super Mar 07 '22 at 13:04
  • How do I dynamically change only car value with javascript in an attribute, without writing truck? How use data-? – maja Mar 07 '22 at 13:29

2 Answers2

2

HTML Attributes must be a string value you can't parse this like a object. For parse attributes you can you JSON.stringify() and JSON.parse() for setting you attribute values.

Example: setting:

const el = document.body 
el.setAttribute("my-attribute", JSON.stringify({car: "bmw", owner: "user1234"}))

and parse

    JSON.parse(document.body.getAttribute('my-attribute'))
vitaliyirtlach
  • 183
  • 1
  • 8
  • after setAttribute how to dynamically change car or owner value separately, without rewriting owner, element.myAttributes.car = "ferrari"? – maja Mar 07 '22 at 13:33
  • I added the code in question. I tried to get Attributes and switch to JSON.parse, but I don't get the result. How do I do this? – maja Mar 09 '22 at 08:07
2

You can use dataset for that purpose. Here is a small demo:

let div = document.querySelector("div");

Object.assign(div.dataset, { water: "Morshinska", juice: "Sandora" });

console.log(div.dataset.water);

div.dataset.water = "Spa";

console.log(div.dataset.water);

console.log(Object.entries(div.dataset)
                  .map(([k, v]) => `${k}: ${v}`)
                  .join("; "));
<div></div>

Solution more close to your format

Although this is not best practice (due to the limitations on the allowed characters in this format), here are some helper functions to get and set individual properties in the attribute syntax you want to use:

function getMyAttributes(elem) {
    const regex = /([^:;=]*):([^:;=]*)/g
    return Object.fromEntries(Array.from(elem.dataset.myattr?.matchAll(regex)??[], ([_, k, v]) =>
        [k.trim(), v.trim()]
    ));
}

function setMyAttributes(elem, obj) {
    const regex = /[:;]/g;
    elem.dataset.myattr = Object.entries(obj).map(([k, v]) => {
        if (regex.test(k) || regex.test(v)) throw "Invalid character in key/value pair";
        return `${k}: ${v};`;
    }).join(" ");
}

function setMyAttribute(elem, key, value) {
    setMyAttributes(elem, {...getMyAttributes(elem), ...{[key]: value}});
}

function getMyAttribute(elem, key) {
    return getMyAttributes(elem)[key];
}

// Demo
let div = document.querySelector("div");
console.log(getMyAttribute(div, "water"));
setMyAttribute(div, "water", "Spa");
console.log(getMyAttribute(div, "water"));
console.log(div.dataset.myattr);
<div data-myattr="water: Morshinska; juice: Sandora;"></div>
trincot
  • 317,000
  • 35
  • 244
  • 286
  • In the div I get two separate data-water = "Spa" and data-juice = "Sandora", and I need data = "whater: Spa; juice: Sandora;" – maja Mar 07 '22 at 13:49
  • You can get that with a simple function. – trincot Mar 07 '22 at 13:50
  • I just read about creating object, can this help: [link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects) – maja Mar 07 '22 at 13:51
  • Objects are the basic stuff in JavaScript. I don't understand why you link to that. `dataset` is such an object. See addition to answer to see how you can produce such string representation. – trincot Mar 07 '22 at 13:52
  • Testing: I'm trying to get attributes of the div, modify it and put it back in this form
    -> just change div.dataset.car = "ferrari" Just like we change the background or color in style.
    – maja Mar 07 '22 at 15:39
  • Ok, so "some similar alternative" that you mentioned is not really what you want. You want it *exactly* like that? – trincot Mar 07 '22 at 15:52
  • Added another solution, but I would not consider this best practice. – trincot Mar 07 '22 at 16:41
  • trincot, a little research and I think your first answer was correct, sorry for doubting, I was looking for a different approach. I changed it a bit and added the code in question, see above. The next problem that arose was how to getAttribute vehicles from id=demo and convert to object? – maja Mar 08 '22 at 17:27