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

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

ただいまの
回答率

90.03%

Angular5で画像アップロード後に該当箇所の画像を動的に変更したいです。

解決済

回答 1

投稿 編集

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

nerianighthawk

score 224

 前提・実現したいこと

サーバサイド: Spring Boot(フロント側で完結する質問なので関係ないかと思います)
フロントエンド: Angular5
ユーザアイコン機能を実装しています。
ユーザ設定画面にて画像アップロード後に画面のリロードをせずにツールバーに表示されているユーザアイコンを切り替えたいです。
詳細は以下の通りです。ご教授よろしくお願いします。

 発生している問題・エラーメッセージ

アイコンのアップロードは完了しており、エラーは出ていません。
アップロードされたファイルはサーバ側のresource\imageフォルダに保存されています。
一方クライアント側では以下のようにimgタグで呼び出しています(authService.userdetail.iconUrlはアイコン取得用のAPIのURL)。

<img [src]="authService.userdetail.iconUrl" class="account_icon" />


また、画面遷移はすべてRouterクラスのnavigateメソッドを使っているため、画面のリロードは行っておらず、ツールバーは全画面共通で固定されています。
この場合、もう一度ログインしなおすか画面をリロードするまでツールバーのアイコンの表示が変わりません。
何か対処方法はあるのでしょうか。

 該当のソースコード

以下がツールバーのソースになります。

<mat-toolbar class="toolbar">
    <button mat-icon-button class="menu_button" (click)="sidenav.toggle()">
        <mat-icon>menu</mat-icon>
    </button>
    <img id="logo" src="../assets/image/logo.png" (click)="nav.toTop()">
    <button mat-button [matMenuTriggerFor]="menu">
        <img *ngIf="!authService.isUserEmpty()" [src]="authService.userdetail.iconUrl" class="account_icon" /> {{ authService.userdetail.lastName + authService.userdetail.firstName }}
    </button>
    <mat-menu #menu="matMenu">
        <button mat-menu-item (click)="nav.toMySetting()">ユーザ設定</button>
        <button mat-menu-item (click)="logout()">ログアウト</button>
    </mat-menu>
</mat-toolbar>


また、以下は一例ですが、画面遷移は以下の通りです。

constructor(private router: Router){}

toTop() {
  this.router.navigate(["/top"]);
}


アイコンアップロードについてはユーザ設定画面でダイアログを開いた後、ダイアログでファイル選択後アップロードボタンを押すことで、アイコンをアップロードできます。アップロード後ダイアログは閉じるようになっています。

 試したこと

  • 画面遷移の度にモデルUserDetailを取り直す。
    モデルにアイコン取得用APIのURLを入れているので、モデルのインスタンスを生成しなおすことで表示も切り替わると考えました。しかし、名前等の入力項目は表示が変わったのですが、アイコンの表示は変わりませんでした。

  • 画像アップロード後にリロードする。
    ダイアログを閉じた後、画面をリロードするようにしたのですが、UIがとても変な感じになってしまいました(他ではリロードされないのにそこだけリロードされるので)。綺麗なUIならこの手法でもいいと思っていますので、何かやり方があるならご教授よろしくお願いします。

 質問事項のまとめ

質問事項がバラついてしまったので、まとめたいと思います。

  1. 画面のリロードを行わずに画像呼び出しを再度行うことは可能でしょうか。可能でしたら方法が知りたいです。
  2. 画像アップロード時の仕様としてリロードしても違和感のないUIを実現するためにはどのようにすればいいでしょうか。

1が可能であれば方法をご教授ください。不可能であれば2を教えて頂きたく思います。
以上、よろしくお願いします。

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • h_daido

    2018/03/22 21:39

    authService.userdetail.iconUrlの値はアップロード前後で変わりますか?キャッシュされているだけとか?

    キャンセル

  • nerianighthawk

    2018/03/22 23:20

    authService.userdetail.iconUrlの値自体は変わりません。アップロードはサーバ側で参照する画像を置き換える操作となります。何もしない限りAngularの画面遷移ではキャッシュに残っている画像を使っていると思います。

    キャンセル

  • h_daido

    2018/03/23 10:42

    我々のサービスも類似環境ですが、authService.userdetail.iconUrlのurlがアップロードのたびに変わるスタイルです。その場合はuserDetailモデルの値を書き換えてあげれば変更されますね。なので、おそらくキャッシュが原因かと思った次第です。なので、1.uthService.userdetail.iconUrlにnullや別urlを一度指定する。2.その後uthService.userdetail.iconUrlに正しい値をセットしなおす。で動けばangularのwatchが正式に稼働して動作するかも。上記でデバッグして動けば対策方法が切り分けできそうです。

    キャンセル

  • nerianighthawk

    2018/03/23 11:37

    h_daidoさんの方法でうまくいきました。ありがとうございます。ベストアンサーとして選びたいのですが、質問に対する回答として入力してもらうことは可能でしょうか。

    キャンセル

回答 1

checkベストアンサー

+1

先ほど追記・修正依頼で記載したものです。

根本的には、img srcにセットされる値が変更されないため、angularのウォッチ式が動かずに変更を検知できておらず、imgの画像を再取得しに行っていないのが原因。となるかと思います。

そこで、追記・修正依頼に記載した策を試みてもらったのですが、これはあくまで原因切り分けのための方法ということで、根本対応としては少しイマイチな気もします。
(理由は、今後対象コードをあなた以外の人がメンテしたときに、「なぜ一度nullをセットしているのか?」がわからないためです)

簡単にググったのですが、下記SOの回答の方がいいかなと思いました。
https://stackoverflow.com/questions/18845298/forcing-a-ng-src-reload

正直こちらも完璧にしっくりくる解決策ではないのですが(回答者の方もあくまで"workaround"といっています)、まだこちらの方がコードから意図が汲み取りやすいと思います。

上記回答を利用する場合には、authService.userdetail.iconUrlで利用するAPI側の人と相談して、影響のないパラメーターをセットしてくださいね。

と、まぁ上記が教科書的な対応と思いますが、私が追記・修正依頼に記載した策でもまぁいいとは思います(ちゃんとコメントに残すのが最低条件ですが)。あとは工数と求める品質とで調整して決めてもらえればと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/03/23 13:13

    丁寧な解答ありがとうございます。
    確かに意図がわからないコードはよくないですね。
    ひとまずコメントで意図は書くようにし、その上で対応方法を考えていきたいと思います。

    キャンセル

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

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