質問です
とりあえずソースコードは次のようになります。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebContent Sample</title>
</head>
<body>
<!--
(参考)
https://developers.google.com/web/fundamentals/web-components/shadowdom?hl=ja
https://html5experts.jp/shumpei-shiraishi/24239/
-->
<script>
class QuestionBox extends HTMLElement {
//*********************************************************************
// Static Methods
//*********************************************************************
static get template(){
return `
<div id="question-str" class="question-cell">
<slot></slot>
</div>
<div class="question-cell">
<input type="radio" name="rd-question" value="0">
<input type="radio" name="rd-question" value="1">
<input type="radio" name="rd-question" value="2">
<input type="radio" name="rd-question" value="3">
<input type="radio" name="rd-question" value="4">
</div>
<style>
.question-cell {
display: table-cell;
}
</style>
`;
}
//*********************************************************************
// Member Methods
//*********************************************************************
constructor(){
super();
}
connectedCallback(){
let sr = this.attachShadow({mode: "open"});
sr.innerHTML = QuestionBox.template;
this.style.display = "table-row";
this.defaultCheck();
}
defaultCheck(){
let ipts = this.shadowRoot.querySelectorAll("input");
let val = this.getAttribute("value");
ipts[val].checked = true;
}
get value(){
const ipts = this.shadowRoot.querySelectorAll("input");
for(let i=0; i<ipts.length; i++){
if(ipts[i].checked){
return parseInt(ipts[i].value);
}
}
}
set value(val){
let ipts = this.shadowRoot.querySelectorAll("input");
this.setAttribute("value", val);
for(let i=0; i<ipts.length; i++){
if(parseInt(ipts[i].value) == val){
ipts[i].checked = true;
}
}
}
}
customElements.define('question-box', QuestionBox);
</script>
<div style="display: table;">
<question-box value="2"><p>質問1です</p></question-box>
<question-box value="0"><p>質問2です</p></question-box>
</div>
<script>
var qs = document.getElementsByTagName("question-box");
for(var i=0; i<qs.length; i++){
console.log(qs[i].value);
qs[i].value += 1;
}
</script>
</body>
</html>
このカスタムタグを作るためのクラスです。
template()、constructor()、connectedCallback()などは前のサンプルと同じことなので説明しません。
属性valueのgetter/setterとシャドウルート以下の要素との連動の説明が主眼です。
「get value()」がgetterです。
これはこのカスタムタグのvalueプロパティを参照した時に取得できる値として機能します。
実際にはカスタムタグ内の<input>のうちcheckedになっているもののvalueを取得します。
this.shadowRoot.querySelectorAll("input")でシャドウルート以下の<input>を取得します。
なお、シャドウルート以下の要素の対してはelement.getElementsByTagName()やelement.getElementsByClassName()は機能しないのでquerySelectorAll()を使用します。
querySelector()とgetElementById()は機能します。
あとは普通にcheckedの<input>を探し、そのvalueを返すだけです。
「set value()」がgetterです。
querySelectorAll()を使っているのはgetterで説明した通りです。
あとは普通にsetterの引数valと一致するvalueを持つ<input>をcheckedにするだけです。
これだけでJSで操作するときのプロパティはもちろん、HTMLから値を設定するときのvalue属性も有効になります。
下がサンプルで、1つめはvalue=2、2つめはvalue=0を属性として指定しています。
質問1です
質問2です
87〜93行目のコードは動作確認です。
console.log()で値が取得できることを確認し、そのあと+1してプロパティの変更が有効なことを確認しています。
実際には次の様になります。
質問1です
質問2です
値の取得はコンソールをみないとダメですが、選択しているラジオボタンが+1されているのが確認できます。