質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

element.setAttributeによる属性の設定

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,104

tera_infinity

score 26

前提・実現したいこと

現在Monacaを用いてアプリ開発の勉強をしていたのですが、element.setAttributeを用いてエレメントの属性を設定する動作を実装した際に、別のページにあるエレメントの属性を設定することができませんでした。
勉強不足な点もあるのですが、仕様なのか実装方法が悪いのかわからない状況です。

該当のソースコード

page2にあるid="sample"のclass属性をnoからyesへ変更するソースです。

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: content: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
<ons-navigator id="nav" page="page1.html"></ons-navigator>

<template id="page1.html">
    <ons-page>
        <ons-button id="push_css" onclick="document.getElementById('nav').pushPage('page2.html'),push_bt()">pushpage</ons-button>
    </ons-page>
</template>

<template id="page2.html">
    <ons-page>
        <div id="sample" class="no">属性変更</div>
        <ons-button id="can_bt" onclick="document.getElementById('nav').popPage()">poppage</ons-button>
    </ons-page>
</template>

<script type="text/javascript">
function push_bt(){
    var element = document.getElementById("sample"); 
    element.setAttribute("class", "yes");
    alert("change_txのrel属性は「"+element.getAttribute("class")+"」です");
}
</script>
</body>
</html>


上記のソースのように別のページの属性を変更しようとすると何も反応しません。

下記のソースのようにボタンとelement.setAttributeを同一のページに実装すると属性の変更ができました。

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: content: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
<ons-navigator id="nav" page="page1.html"></ons-navigator>

<template id="page1.html">
    <ons-page>
        <ons-button id="push_css" onclick="document.getElementById('nav').pushPage('page2.html'),push_bt()">pushpage</ons-button>

        <div id="sample" class="no">属性変更</div>
    </ons-page>
</template>

<script type="text/javascript">
function push_bt(){
    var element = document.getElementById("sample"); 
    element.setAttribute("class", "yes");
    alert("change_txのrel属性は「"+element.getAttribute("class")+"」です");
}
</script>
</body>
</html>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

 template要素 (template element)

The template contents of a template element are not children of the element itself. Instead, they are stored in a DocumentFragment associated with a different Document without a browsing context so as to avoid the template contents interfering with the main Document. (For example, this avoids form controls from being submitted, scripts from executing, and so forth.) The template contents have no conformance requirements.

機械翻訳「テンプレート要素のテンプレート内容は、要素自体の子要素ではありません。その代わりに、テンプレートの内容がメイン文書と干渉しないように、閲覧コンテキストなしで別のドキュメントに関連付けられたDocumentFragmentに格納されます。 (たとえば、これにより、フォームコントロールの送信、スクリプトの実行などが回避されます)。テンプレートのコンテンツには、適合要件はありません。」

従って、template要素の子にノードは存在せず、getElementByIdquerySelectorAll 等の検索範囲に存在しない事になります。

console.log(document.querySelector('template').childNodes.length);  // 0

template要素の役割は、雛形となるDOMを生成する事にあり、DOMツリー上にそれが存在する場合、「複製」ではなく、「移動」となってしまう可能性が考慮されているものと思われます。
一応、template要素ノードの content プロパティから DocumentFragment ノードを参照できる為、子を辿っていけば、当該要素ノードを参照する事は可能です。

<template id="page1.html">
  <ons-page>
    <ons-button id="push_css" onclick="document.getElementById('nav').pushPage('page2.html'),push_bt()">pushpage</ons-button>
    <div id="sample" class="no">属性変更</div>
  </ons-page>
</template>
<script>
console.log(document.getElementById('page1.html').content.firstElementChild.firstElementChild);
</script>

雛形からノードに落とし込む場合は、document.importNode() を使います。

console.log(document.importNode(document.getElementById('page1.html').content).getElementById('push_css'));

雛形の生成から始めるのなら、template要素ノードの生成から始めるべきだと思います。

 別のページをノードを操作する

上記のソースのように別のページの属性を変更しようとすると何も反応しません。

Monaca を知らない為、どういう構成になっているのかがソースから読み取れませんが、別の文書には別の document が存在するはずなので、当該 document を参照する方法を探してください。
page1.html 内で宣言する document.getElementById は page1.html 内にあるDOMノードしか検索できません。
例えば、page2文書の document オブジェクトが page2Document であるならば、page2Document.getElementById で page2文書内の id を持つ要素ノードを検索できるはずです。

Re: tera_infinity さん

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/15 15:48

    回答ありがとうございます!
    詳しく説明してくださって助かります。どちらの実装方法もまだ試したことがなかったので、実際に試してみようと思います。

    キャンセル

0

テンプレートが同期処理になっていないからでは?
promiseなどで処理順を指定してみてはどうでしょう?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/15 15:49

    回答ありがとうございます!
    promiseは使ったことがないので勉強しつつ実装してみようと思います

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る