0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[ODC]ページ内の特定箇所へのリンクに対応する

Posted at

大量のコンテンツがあるScreenで、特定の箇所を共有したい(URLを開くと、その箇所へスクロールさせたい)。

環境情報

ODC Studio(Version 1.5.9)

先に結論

以下の実装が良さそう。

  1. Screenにスクロール先WidgetのIdを渡すInput Parameterを追加
  2. ScreenのOnReadyで以下の処理
    1. 渡されたWidgetのIdが許容される値かチェックする
    2. 許容される値であれば、OutSystemsUI/ScrollToElement ActionのWidgetIdパラメータに渡す

一般のWebページならURLにFragmentを付与すれば良い

URI フラグメント - URI | MDNより、FragmentはURL内の#で始まる部分。

フラグメントは URI の最後の部分で、# の文字で始まる部分です。文書内のセクションや動画内の位置など、リソースの特定の部分を識別するために使用されます。

HTMLでページを開いた時、特定の場所にスクロール表示するには、URL末尾に「#要素のid」を追加する。

HTML 文書内の場合は、要素の id 属性となり、ブラウザーはその要素までスクロールします。

OutSystemsアプリケーションでは、この方法はうまくいかない。
以下、この点について確認し、解決策を検討する。

検証用Screenの実装

Sectionを3つ配置し、Nameプロパティを、それぞれSection1, Section2, Section3とした。
スクリーンショット 2025-03-01 23.26.36.png

Section1に対応するHTMLのタグ構造。
スクリーンショット 2025-03-01 23.35.25.png

URLにFragmentを付与するだけだとうまくいかない

画面上のSection1にスクロールした状態で開きたいとき、以下のアドレスにアクセスする。
「https://<FQDN>/<App名>/<Screen名>#Section1」

一般のWebページならこれでうまくいくのだが、OutSystemsではうまくいかない。

恐らくReactの影響かと思われる(OutSystemsは、内部でReactを使っている)。

  • ReactとFragmentをキーワードにして検索すると、同じ問題にぶつかっている投稿がいくつかある
  • SPAであるから、サーバーから返されるHTMLは枠だけが記述されていて、後からJavaScriptでページ構築される? → 取得時には遷移先となる場所がない

OutSystemsUI/ScrollToElement ActionでFragmentまでスクロール → 可能だが問題あり

JavaScriptでFragmentを取得

現在のURL内のFragmentはJavaScriptを使えば取得できる。
window.location.hashを使う。
Location: hash property - Web APIs | MDN

JavaScript要素をAction Flowに配置し、Output ParameterとしてFragmentを追加。

コード例。
window.location.hashは#で始まるが、Fragmentがないときは空文字列を返す。値が入っているか確認し、入っているときは、先頭の1文字を削って返している。

$parameters.Fragment = window.location.hash;
if ($parameters.Fragment.startsWith('#'))
    $parameters.Fragment = $parameters.Fragment.substring(1);

ScreenのOnReadyでScrollさせる

ScreenのOnReady Eventを選ぶのは、必要なDOMの準備が終わったタイミングで、1回の画面表示につき1回だけ発生するEventであるため。

OnReadyのハンドラー例。
JavaScriptコードで取得したFragmentをWidgetIdパラメータに設定してScrollToElement Actionを呼ぶ。
スクリーンショット 2025-03-02 11.21.28.png

補足

  • ListAppendAllでは、画面上でスクロール先として使えるWidgetのIdを、Local VariableのListに登録している
  • GetFragmentの実装は、↑に示したJavaScript
  • ListIndexOfで取得したFragmentが使えるIdと合致するかチェックしている(これは明示的に許可した値だけを利用可能にすることで、セキュリティに想定外の問題が起きるのを防ぐため)
  • 許容されるFragmentであれば、ScrollToElementにGetFrgmentの結果を渡してスクロールさせる

結果

ブラウザのアドレスバーにFragment付きのURLを入力して開いたところ、想定通り、指定した要素までスクロールして開いた。

しかし、以下のパターンの操作をすると、画面が全面白の状態のまま表示が止まってしまう(通信によってページのHTML自体は取得できている)。

  1. 一度ページを開く
  2. アドレスバーのURLを編集し、Fragmentを別の値に変更する
  3. アドレスバーでEnterキー

これもReactが原因の気がする。
TODO: Reactを後で調べる

FragmentでなくScreenのInput Parameterでスクロール先を指定する

基本的な方法は↑と同じだが、Fragmentではなく、Screenに追加したInput Parameterでスクロール先を指定する(↓の例では、TargetInThePage)。
スクリーンショット 2025-03-02 11.34.43.png

OnReadyの実装は基本的に同じで、GetFragment呼び出しを無くし、そのOutput Parameterの代わりにTargetInThePageを使うだけ。
スクリーンショット 2025-03-02 11.37.07.png

この方法なら、アドレスバーでパラメータを変更→Enterキーの操作でも問題なく再表示できた。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?