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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

AngularJS

AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

Onsen UI

HTML5で記述されたモバイルアプリの高速化、およびネイティブアプリライクなUIが作れるフレームワーク。 様々なJavaScriptフレームワークと併せて使用することができます。スマートフォン向けアプリ、Webサイトに必要なアニメーション、UI/UXを実装することが可能になります。

Monaca

「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

Q&A

解決済

1回答

1362閲覧

コントローラAで取得したデータを非同期的にコントローラBに表示したい

shori0128

総合スコア29

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

AngularJS

AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

Onsen UI

HTML5で記述されたモバイルアプリの高速化、およびネイティブアプリライクなUIが作れるフレームワーク。 様々なJavaScriptフレームワークと併せて使用することができます。スマートフォン向けアプリ、Webサイトに必要なアニメーション、UI/UXを実装することが可能になります。

Monaca

「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

0グッド

1クリップ

投稿2017/12/11 08:08

編集2017/12/11 09:31

###前提・実現したいこと
いつもお世話になっています。
angularjs+onsenuiでアプリの開発をしております。

コントローラAでローカルから取得したデータをコントローラBでlazy-repeatで非同期的に表示させたいと考えております。
コントローラ間でデータの共有はできるようになったのですが、コントローラAでデータの取得が完了する前に、コントローラBで画面が表示されてしまうため、うまく表示されません。

なので、コントローラAで読み込みが終わったタイミングでコントローラBに終わったことを通知し、表示できればと思ったのですが、記述方法が分かりません。

以下に抜粋したソースを記載しますので、上記方法、もしくはその他に最適な方法をご存じの方がいらしたらご教示いただけますでしょうか。

###該当のソースコード

javascript

1'use strict'; 2 3const kijiFolder = 'kiji'; 4const gazoFolder = 'image'; 5const pageOption = { 6 animation: 'slide' 7}; 8 9let appDir, gazoDir, kijiDir, destination; 10 11ons.bootstrap() 12 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 13 // 共通 14 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 15 .controller('commonCtrl', function ($scope, sharedScope) { 16 $scope.item = [{ 17 src: 'icon/gif-load.gif', 18 orgSrc: '', 19 date: 'Loading...', 20 size: 'Loading...' 21 }]; 22 23 sharedScope.setScope('gazoCatalogCtrl', $scope.item); 24 25 //■ データフォルダへアクセス 26 resolveLocalFileSystemURLSync(cordova.file.dataDirectory) 27 .then(function (fs) { 28 appDir = fs; 29 let process = []; 30 process.push(getDirectorySync(appDir, kijiFolder)); 31 process.push(getDirectorySync(appDir, gazoFolder)); 32 return Promise.all(process); 33 }) 34 .then(function (fsArray) { 35 kijiDir = fsArray[0]; 36 gazoDir = fsArray[1]; 37 showGazo(); 38 }) 39 .catch(getErr); 40 41 //■ 画像一覧の取得 42 const showGazo = function () { 43 const dirObj = gazoDir.createReader(); 44 45 readEntriesSync(dirObj) 46 .then(function (fileArray) { 47 //実画像(=jpg画像)のみ抽出してメタデータ取得 48 return Promise.all(fileArray.filter(function (fileObj) { 49 const ext = fileObj.name.split('.')[1]; 50 if (ext == 'jpg') return fileObj; 51 }) 52 .map(function (fileObj) { 53 return getMetadataSync(fileObj); 54 })); 55 }) 56 .then(function (fileArray) { 57 //ファイル一覧をタイムスタンプ順(昇順)にソート 58 fileArray.sort(function (a, b) { 59 if (a.metadata.modificationTime > b.metadata.modificationTime) return -1; 60 if (a.metadata.modificationTime < b.metadata.modificationTime) return 1; 61 return 0; 62 }) 63 .forEach(function (fileObj, index) { 64 let localItem = []; 65 const src = fileObj.toURL(); 66 67 localItem.push({ 68 src: src.replace('.jpg', '.thm'), 69 orgSrc: src, 70 date: fileObj.metadata.modificationTime, 71 size: fileObj.metadata.size 72 }); 73 74 $scope.item = localItem; 75 sharedScope.setScope('gazoCatalogCtrl', $scope.item); 76 }); 77 }) 78 .catch(getErr); 79 }; 80 }) 81 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 82 // 画像一覧 83 //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 84 .controller('gazoCatalogCtrl', function ($scope, sharedScope) { 85 $scope.delegate = { 86 configureItemScope: function (index, itemScope) { 87 const gazoCatalogCtrlScope = sharedScope.getScope('gazoCatalogCtrl'); 88 itemScope.item = { 89 src: gazoCatalogCtrlScope[index].src, 90 orgSrc: gazoCatalogCtrlScope[index].orgSrc, 91 date: gazoCatalogCtrlScope[index].date, 92 size: gazoCatalogCtrlScope[index].size 93 }; 94 }, 95 calculateItemHeight: function (index) { 96 return 91; 97 }, 98 countItems: function () { 99 return $scope.item.length; 100 } 101 }; 102 }) 103 .factory('sharedScope', function ($rootScope) { 104 let sharedScope = {}; 105 106 return { 107 setScope: function (key, value) { 108 sharedScope[key] = value; 109 }, 110 getScope: function (key) { 111 return sharedScope[key]; 112 } 113 }; 114 });

html

1<!DOCTYPE HTML> 2<html> 3 4<head> 5 <meta charset="utf-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> 7 <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'"> 8 <script src="components/loader.js"></script> 9 <script src="lib/angular/angular.min.js"></script> 10 <script src="lib/onsenui/js/onsenui.min.js"></script> 11 <script src="lib/onsenui/js/angular-onsenui.min.js"></script> 12 <script src="ext/imageResizer/resize.js"></script> 13 <script type="text/javascript" src="func.js"></script> 14 <script type="text/javascript" src="promise.js"></script> 15 <script type="text/javascript" src="index.js"></script> 16 17 <link rel="stylesheet" href="components/loader.css"> 18 <link rel="stylesheet" href="lib/onsenui/css/onsenui.css"> 19 <link rel="stylesheet" href="lib/onsenui/css/onsen-css-components.css"> 20 <link rel="stylesheet" href="css/bootstrap-4.0.0-beta-dist/css/bootstrap.min.css"> 21 <link rel="stylesheet" href="css/selectBox.css"> 22 <link rel="stylesheet" href="css/style.css"> 23</head> 24 25<body> 26 <ons-navigator id="appNavi" page="common.html"></ons-navigator> 27 28 <ons-template id="tabNavi1.html"> 29 <ons-navigator id="tabNavi1" page="kijiCatalog.html"></ons-navigator> 30 </ons-template> 31 32 <ons-template id="tabNavi2.html"> 33 <ons-navigator id="tabNavi2" page="gazoCatalog.html"></ons-navigator> 34 </ons-template> 35 36 <ons-template id="tabNavi3.html"> 37 <ons-navigator id="tabNavi3" page="templateEdit.html"></ons-navigator> 38 </ons-template> 39 40 <ons-template id="gazoCatalog" ng-controller="gazoCatalogCtrl"> 41 <ons-page> 42 <ons-list> 43 <ons-list-item class="item" ons-lazy-repeat="delegate" modifier="chevron" tappable> 44 <ons-row ng-click="openGazoEdit($index)"> 45 <ons-col width="80px"> 46 <img class="thumb" ng-src="{{item.src}}" original-src="{{item.orgSrc}}"></img> 47 </ons-col> 48 <ons-col> 49 <header> 50 <span class="title">スポニチ越中島にて記..</span> 51 <span class="label">{{item.date}}</span> 52 </header> 53 <p class="etc">W: 1000 x H: 1000</p> 54 <span class="etc">{{item.size}}</span> 55 <span align="right"> 56 <input type="checkbox" class="check" name="select"> 57 </span> 58 </ons-col> 59 </ons-row> 60 </ons-list-item> 61 </ons-list> 62 </ons-page> 63 </ons-template> 64</body> 65 66</html>

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

すみません、実際に試してはいないのですが以下のようなコードでいかがでしょう?
スコープへの反映をループ内で行うのをやめました。

javascript

1 .then(function (fileArray) { 2 var localItem = []; 3 //ファイル一覧をタイムスタンプ順(昇順)にソート 4 fileArray.sort(function (a, b) { 5 if (a.metadata.modificationTime > b.metadata.modificationTime) return -1; 6 if (a.metadata.modificationTime < b.metadata.modificationTime) return 1; 7 return 0; 8 }) 9 .forEach(function (fileObj, index) { 10 const src = fileObj.toURL(); 11 localItem .push({ 12 src: src.replace('.jpg', '.thm'), 13 orgSrc: src, 14 date: fileObj.metadata.modificationTime, 15 size: fileObj.metadata.size 16 }); 17 }); 18 $scope.item = localItem ; 19 sharedScope.setScope('gazoCatalogCtrl', $scope.item); 20 })

もしくは、例えば

1.コントローラAを生成し、データを取得し格納しておく要素をXで宣言する。
2.コントローラBを生成し、データを取得し格納しておく要素をYで宣言する。
3.コントローラBの要素Yについて、コントローラ外、例えばServiceCに格納されているオブジェクトZを参照するように代入する。※オブジェクトZは必ずオブジェクトか配列で宣言しておく
4.コントローラAでデータを取得し、要素Xにデータを代入していく。
5.データの取得が終わったら、要素XをServiceCのオブジェクトZに代入する。

上記手順でもなんとかなるかと思います。
コントローラBの要素YはオブジェクトZのアドレスを保持しているため、アドレス内の要素が書き換わったときにデータがコントローラBに反映されます。
アドレス内の要素の書き換えはコントローラAで行います。

投稿2017/12/11 08:49

編集2017/12/11 08:56
akabee

総合スコア1947

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shori0128

2017/12/11 09:31

>akabee様 いつもお世話になっております。 いただいた回答をもとに早速改良を加えたのですが、うまく動作しません。。 動作はしているのですが、取得したデータが動的に画面に表示されない状態です。 なぜか、pushPage、popPage等で画面遷移を行うと取得データの一覧が表示されてくる状態です。 データ取得後に、コントローラBに対して何かキックしてあげる必要があるのかと思ったのですが、原因はなんでしょうか。 改良後のソースとHTMLを追記しました。 ご確認いただけないでしょうか。
akabee

2017/12/11 10:08

改良後のソースについて詳細な確認をしたわけではありませんが、そのような「値は反映できているようだが即座に画面表示されない」症状ですとまず$scope.$applyを試してみたくなりますね。 参考→http://yutawatanabe.hatenablog.com/entry/angularjs-scope-apply AngularJSでは値が変更されると動的に画面表示が切り替わりますが、これは「AngularJSの中の何か(私も詳しくは理解していません)」が頑張ってコード内を監視していて、何か値が切り替わったら、それを画面表示にリアルタイムに反映すべく、頑張って見張ってくれているためです。 ですが、「AngularJSの監視外」で値が切り替わった場合、即時に画面表示に反映されないということがあります。その場合、「画面表示に反映」ということを手動で行う必要があるのですが、それが「$scope.$apply」という処理です。 実は私は「$scope」は好みに合わず利用していませんので自信がありませんが、 sharedScope.setScope('gazoCatalogCtrl', $scope.item); の次に $scope.$apply でどうでしょう。改善されなければ申し訳ありません。
shori0128

2017/12/12 05:37

>akabee様 お世話になっております。 いただいた改善案を実施したところ。。。うまく動作するようになりました! 大変勉強になりました。 また別で回答いただける機会がありましたら宜しくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問