いいサンプルをご存知の方は教えてください。よろしくお願いいたします。
面白そうだったので、サンプルコードを作って公開しておきました。
https://github.com/masa-ottii/angular7-ngbootstrap-dialog-sample
なにか質問があれば、引き続き受け付けます。
OTTiさん早速サンプルコードありがとうございます。
現状の進捗を返答します。
OTTiさんのコードを早速自分のコードに組み込んでいるのですが、引き続きエラーが出てダイアログが表示されませんでした。
そこで https://bit.ly/2BE0epj を参考に、ngAfterViewInit内にsetTimeoutを入れてその中にopen()を入れたところダイアログが表示されるようになりました。
しかしながら、今度はSaveボタンからダイアログを閉じようとしたところ該当HTML行 modal.close('Save click') にて TypeError: Cannot read property 'close' of undefined がでて試行錯誤しています。
そこで一度OTTiさんのコードを動かす状態にして詳細を調べようかどうか…と悩んでいたところです。
この返答だけではなんのことやらわからないと思いますが、コードは安易に出せないのでうまく説明できずすみません。
> Cannot read property 'close' of undefined
この場合、modalが未定義だというエラーなので、
> 該当HTML行 modal.close('Save click')
このHTMLテンプレートを使っているコンポーネントにmodalというプロパティはありますでしょうか?
返答ありがとうございます
質問に対し質問で返すことになり申し訳ないのですが、OTTiさんの my-dialog.component.ts ではどこでmodalプロパティを定義しているのでしょうか?
見つからないので、htmlファイル上で最初に「<ng-template #dialog let-modal>」を入れればmodalプロパティが定義されるのか?と考えていました。
あと、OTTiさんの angular7-ngbootstrap-dialog-sample-master について node_modules をコピーして ng serve --open --port 4201 したところ、以下のエラーが出て動かず悩んでいます。
ERROR Error: StaticInjectorError(AppModule)[NgbModal -> NgbModalStack]:
StaticInjectorError(Platform: core)[NgbModal -> NgbModalStack]:
NullInjectorError: No provider for NgbModalStack!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:3207)
at resolveToken (core.js:3452)
at tryResolveToken (core.js:3396)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:3293)
at resolveToken (core.js:3452)
at tryResolveToken (core.js:3396)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:3293)
at resolveNgModuleDep (core.js:19763)
at _createClass (core.js:19812)
at _createProviderInstance (core.js:19780)
VM1055:37 TypeError: Converting circular structure to JSON
at JSON.stringify (<anonymous>)
at console.window.console.error (<anonymous>:39:101)
at Object.View_AppComponent_0 (AppComponent.html:6)
at Object.proxyClass [as factory] (compiler.js:17945)
at DebugContext_.push../node_modules/@angular/core/fesm5/core.js.DebugContext_.logError (core.js:22708)
at ErrorHandler.push../node_modules/@angular/core/fesm5/core.js.ErrorHandler.handleError (core.js:14624)
at core.js:16706
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:138)
at NgZone.push../node_modules/@angular/core/fesm5/core.js.NgZone.runOutsideAngular (core.js:16094)
質問ばかりで恐縮ですが、よろしくお願いします。
let-modalという記述で、このテンプレートを利用しているクラス(NgbModal)から開いた状態のモーダルダイアログのオブジェクトが渡されているようです。
↓こちらとかわかりやすいかも?
https://qiita.com/hedrall/items/b05eb45eb1a50b3436a9
>ERROR Error: StaticInjectorError(AppModule)[NgbModal -> NgbModalStack]:
コピーしたnode_modulesが不完全なんですかね?
angular7-ngbootstrap-dialog-sample-masterフォルダの中で
npm install
して新たに依存モジュールを全部ダウンロードしてくるわけにいかないでしょうか?
もう少し補足
let-modalという風に特に代入されるプロパティを指定していない場合は
$implicit
というプロパティ名を暗黙の名前にしてオブジェクトを渡してきます。
下記のソースコード内で”$implicit”で検索するとModalのオブジェクトを入れてるぽいのが見れます。
node_modules/@ng-bootstrap/ng-bootstrap/fesm2015/ng-bootstrap.js
OTTiiさん、お世話になっております
> angular7-ngbootstrap-dialog-sample-masterフォルダの中で
> npm install
> して新たに依存モジュールを全部ダウンロードしてくるわけにいかないでしょうか?
npm install したら、サンプルプログラムは動作しました。
これです!考えていた通りの動作です。
なぜ自分の方はだめなのか、もう少し考えてみますorz
自分のプログラムにおける component.ts について
this.modalService.open(content,
を
this.modalRef = this.modalService.open(content,
に変更し
component.htmlについて
<ng-template #content let-modal>
↓
<ng-template #content let-modalRef>
modal.close('dialog')
↓
modalRef.close('dialog')
に直せばプロパティがきちんと伝わってcloseできるかと思ったのですが、改善していないようです。
〇〇Component.html:15 ERROR TypeError: Cannot read property 'close' of undefined
at Object.eval [as handleEvent] (〇〇Component.html:15)
at handleEvent (core.js:21652)
at callWithDebugContext (core.js:22746)
at Object.debugHandleEvent [as handleEvent] (core.js:22449)
at dispatchEvent (core.js:19101)
at core.js:19548
at HTMLButtonElement.<anonymous> (platform-browser.js:993)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:16126)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
表示されたモーダルのオブジェクトはng-bootstrapの中で持ち回ってくれてるので、前半部分のコーディングはサンプルのままでいいはずです。
> Cannot read property 'close' of undefined
原因はなんなんでしょうね?
ソースコード全体を見れるとわかるのかもしれないですが・・・。
なんかちょっとした事なような気がします・・・
例えば〇〇Component.htmlの15行目より前にmodalという変数を別に宣言してたりしないですよね?
OTTiiさんひきつづきありがとうございます。
> 例えば〇〇Component.htmlの15行目より前にmodalという変数を別に宣言してたりしないですよね?
いや、検索を使っていましたが、宣言は見つかりませんでした。
今まで細かくコードを見直していましたが、この辺のコンポーネント類についてフォルダごと一度削除して作り直したほうが案外解決の近道かもしれないと考えています。
あと考えうるのが、
<ng-template #content let-modal>
</ng-template>
とやっている「外側」で
modal.close('dialog')
とやっていたりとかはどうでしょう?
let-modalで用意されるmodalという変数は、let-modalが記述されているng-template要素内でのみ有効ですので。
OTTiiさん返答ありがとうございます。
外側にボタンをおいて動作させてみたところ、エラーの行数以外は同じエラーが出ました。
何らかの理由でmodalプロパティの読み取りに失敗しているのは確かなのですが、なぜかはわからないのは相変わらずです。
今日はいろいろありましてまだ作り直しは試していないので、これからやってみるところです。
ERROR TypeError: Cannot read property 'close' of undefined
at Object.eval [as handleEvent] (〇〇Component.html:19)
at handleEvent (core.js:21652)
at callWithDebugContext (core.js:22746)
at Object.debugHandleEvent [as handleEvent] (core.js:22449)
at dispatchEvent (core.js:19101)
at core.js:19548
at HTMLButtonElement.<anonymous> (platform-browser.js:993)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:16126)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
作り直すに当たり、今回は仕様にそうよう修正していたポイントを、ほぼOTTiiさんのコードを写経してみましたが、Saveボタンを押したらまたエラーが出てきました。
出たエラーは
ERROR TypeError: Cannot read property 'close' of undefined
at Object.eval [as handleEvent] 的なものです。
何がまずいのか…。
〇●.component.ts の中身はこんな感じです。
import { Component, OnInit, ViewChild } from '@angular/core';
import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-config-〇●-insert',
templateUrl: './insert.component.html',
styleUrls: ['./insert.component.scss']
})
export class 〇●InsertComponent implements OnInit {
@ViewChild('content') dialogTemplate: Element;
closeResult: string;
constructor(private modalService: NgbModal) {}
ngOnInit() {
this.closeResult = "";
}
ngAfterViewInit(): void {
setTimeout(() => {
this.open(this.dialogTemplate);
});
}
open(content) {
this.modalService.open(content, {ariaLabelledBy: 'modal-basic-title'}).result.then(
(result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
}
);
}
private getDismissReason(reason: any): string {
if(reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
}
〇●.component.html の中身はこんな感じです。
※ソースコードそのまま上げたら表記がおかしくなったので、全角に直しました。
<ng-template #content let-modal>
<div class=”modal-header”>
<h4 class=”modal-title” id=”modal-basic-title”>Profile update</h4>
<button type=”button” class=”close” aria-label=”Close” (click)=”modal.dismiss(’Cross click’)”>
<span aria-hidden=”true”>&times;</span>
</button>
</div>
<div class=”modal-body”>
<form>
<div class=”from-group”>
<label for=”dateOfBirth”>Date of birth</label>
<div class=”input-group”>
<input id=”dateOfBirth” class=”form-control” placeholder=”yyyy-mm-dd” name=”dp” ngbDatepicker #dp=”ngbDatepicker”>
<div class=”input-group-append”>
<button class=”btn btn-outline-secondary calendar” (click)=”dp.toggle()” type=”button”></button>
</div>
</div>
</div>
</form>
</div>
<div class=”modal-footer”>
<button type=”button” class=”btn btn-outline-dark” (click)=”modal.close(’Save click’)”>Save</button>
</div>
</ng-template>
<pre>{{closeResult}}</pre>
なお、『<button type=”button” class=”close” aria-label=”Close” (click)=”modal.dismiss(’Cross click’)”>』について。
今まで仕様に合わせて削っていたのでテストしていませんでしたが、今回試してみたところ、やはりmodalつながりでエラーが出ました。
ERROR TypeError: Cannot read property 'dismiss' of undefined
at Object.eval [as handleEvent] (〇●Component.html:4)
at handleEvent (core.js:21652)
at callWithDebugContext (core.js:22746)
at Object.debugHandleEvent [as handleEvent] (core.js:22449)
at dispatchEvent (core.js:19101)
at core.js:19548
at HTMLButtonElement.<anonymous> (platform-browser.js:993)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:16126)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
その後、
http://blog.yuhiisk.com/archive/2018/05/04/update-angular-to-v6.html
を参考に、同上のソースにおいて、angularのアンインストールと再インストールをやってみたらmodal関係のエラーが出なくなり、モーダル上の操作によって×を押したときもsaveを押したときも{{closeResult}}の値が変わるようになりました。
自分のオリジナルコードの方でも、Angularのインストールでおかしなところがあったのかもしれません。
とりあえず、OTTiiさんの内容から仕様の内容へカスタマイズをさせていただきます。
ありがとうございました。
以下参考:問題解決のためコマンドプロンプトから実施したコマンド
npm install -g @angular/cli@latest
ng update @angular/cli
ng update @angular/core
ng update @angular/material
※Package not installed: "@angular/material". Skipping.と返されたので、多分不要
npm install -g rxjs-tslint
rxjs-5-to-6-migrate -p src/tsconfig.app.json
※Cannot find any possible migrations と出たので、多分不要
npm uninstall rxjs-compat
※コマンド実行後、○×.component.ts の @Component({なんとか}); について急にエラー出だしたので、多分不要
npm install -g rxjs-tslint
ng serve --open
問題は解決したということですかね。
お疲れ様でした。よかったです。
コメントはありません