Reputation: 1096
I am trying to wrap an input field inside a custom element.
The custom element DOM looks like this:
<custom-element>
<div class="fancy-wrapper">
<input value="4">
</div>
<custom-element>
While the element should work like this:
<custom-input id="test"></custom-input>
<script>
let test = document.getElementById('test')
console.log(test.value); // should return 4 (value of inner input)
test.onkeydown = function(e){
console.log(e.target.value); // should the new value of the inner input
};
</script>
Is there any way to get the <custom-input>
attributes redirected to the <input>
attributes inside it, without connecting everything by hand?
Upvotes: 1
Views: 1085
Reputation: 12152
You can append to the innerHTML of the custom element tag
var string="<input type='text' ";
document.getElementById('test').onclick = function(e){
var attr=[...document.querySelector('#test').attributes].map(attr => attr.nodeName);
attr.forEach((e)=>{
var val=document.getElementById('test').getAttribute(e);
string+=e+"="+val + " ";
})
document.getElementById("test").innerHTML+=string + '//>' ;
console.log(document.getElementById("test").outerHTML)
};
<custom-input id="test">dd</custom-input>
Upvotes: 0
Reputation: 21183
No, it is no different than having one DIV and another child DIV
You have to make the connection between the CustomElement and content yourself.
One way is to define a Get/Set function on your Custom-Element that fetches the value of a child input
Instead of manually declaring Get/Set You can ofcourse loop any child element and assign on the CustomElement with defineProperty or Proxies
Example below creates 2 INPUT fields and a this.input
array:
<number-and-range>
<input type="number"> // this.input[0]
<input type="range"> // this.input[1]
</number-and-range>
And connects (GET/SET) <number-and.range>.value
to this.input[0]
customElements.define('number-and-range', class extends HTMLElement {
get value() {
return this.input[0].value;
}
set value(val) {
//input validation should go here
this.input[0].value = val;
console.clear();
console.log('new value:',val);
}
connectedCallback() {
this.input = ['number', 'range'] //create [0] and [1] values in array
.map((type, idx) => Object.assign(
this.appendChild(document.createElement('input')), {
type,
min: 20,
max: 50,
oninput: _ => this.value = this.input[~~!idx].value = this.input[idx].value //toggle [0] and [1]
}));
this.value = 42;//default value
}
});
let el=document.querySelector('number-and-range');
console.log(el.value);
el.value=99;
<body>
<h3>Custom Element : Connected INPUT and Range slider</h3>
Please enter a number between 20 and 50, or use the range slider
<p>
<number-and-range></number-and-range>
</p>
</body>
Upvotes: 2
Reputation: 1680
HTML:
<custom-element id="test">
<div><input value="43" /></div>
</custom-element>
JavaScript:
class CustomElement extends HTMLElement {
constructor() {
super();
const currentDocument = document.currentScript.ownerDocument;
this.template = currentDocument.querySelector('input');
}
get value() {
return this.template.getAttribute('value');
}
set onkeydown(cb) {
return this.template.addEventListener('keydown', cb);
}
}
window.customElements.define('custom-element', CustomElement);
let test = document.getElementById('test');
console.log(test.value);
test.onkeydown = function(e) {
console.log(e.target.value);
};
Can take a look at demo
Upvotes: 0
Reputation: 1018
If I understood your question, you want to copy all the attributes of the custom-element
to the input
tag.
What you can do is,
//get all attributes of custom element
var el = document.getElementById ('test');
// get all attributes
var attrs = el.getAttributeNames(); // returns an array
// loop over attrs array and append the attribute and value in the input,
// I am assuming, you will not add copy id attribute here.
var input = el.getElementsByTagName ('input')[0];
for (var index = 0; index < attrs.length; index++) {
if (attrs[index] !== 'id') {
// set attribute of input with attribute name from the array,
// and get the value from from input.
input.setAttribute (attrs[index], el.getAttribute (attrs[index]));
}
}
It's an idea, you can do something else.
Upvotes: 0